⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dupuart.doc

📁 串口通信小程序
💻 DOC
字号:

A Software Duplex UART for the 751/752                                  AN446

The following program contains routines that will allow an 8xC751 or 8xC752 to 
implement a software UART that can send and receive serial data 
simultaneously. Other published software UARTs only allow either transmit or 
receive to occur at any one time. The demo application shown in the code 
listing waits for data to be received, then echoes it and follows this with a 
hexadecimal interpretation of the data plus a space. For instance, if the 
program receives the character "$", it echoes back the string "$24".  The 
reason for echoing these additional characters is to make it easy to force the 
receiver buffer to fill up in order to test the handshaking. If the program 
simply echoed what was received, it would likely never use more than the very 
first receiver buffer location since it can normally transmit just as fast as 
it can receive. 


CHIP RESOURCES

The UART routines use about 400 bytes of code space and use the timer to 
provide a constant time interrupt to synchronize both transmit and receive 
operations. The hardware connections require four device pins to accomplish 
serial I/O with RTS/CTS handshaking. Only two pins would be needed if 
handshaking is not required. Three of the four pin functions may be assigned 
to any port pin. The serial input pin must be assigned as one of the external 
interrupt pins. Another two pins are used in the demo application to input a 
selection of one of four baud rates (1200, 2400, 4800, or 9600). 


LIMITATIONS

To obtain duplex operation, a fairly large portion of the chip's time is used. 
The routines were tested up to 9600 baud running on a 16 MHz 87C751. When 
serial input and output were both occurring at the same time, the routines 
could not support continuous operation with no pauses between characters. At 
4800 baud, full speed tight reception and transmission worked flawlessly. In 
other words, 4800 baud should work with all applications, while 9600 baud may 
not work with all applications. 


THEORY OF OPERATION

There are three possible sequences of events when serial transmit and receive 
may both be operating at once: transmit and receive begin simultaneously; 
transmit is requested while the receiver is busy; and receive starts while the 
transmitter is busy. The first 2 cases could be handled fairly simply with 
only one interrupt for each bit time. In the first case, everything is already 
in synch and only one timer and one interrupt per bit is needed to do both 
operations. In the second case (transmit is requested while the receiver is 
busy) the program could just wait for the next bit time to start transmitting. 
Unfortunately, the third case presents a problem. If the program is already 
transmitting, it cannot always wait for the next bit time to start sampling 
the serial data if the application is not to lose bits. Also, the timer cannot 
be adjusted to the incoming data since this would distort the duration of one 
of the transmitted bits. 

The method used here to deal with this problem is to always divide all bit 
times into 4 sub-bit times. When transmission and/or reception is in progress, 
the timer runs at 4X the bit rate for the selected baud rate. The variables 
TxTime and RxTime are used to count sub-bit times for the transmitter and the 
receiver, respectively. Both are initialized to a negative value and count up 
to simplify testing for an active sub-bit time. The maximum baud rate that can 
be supported is essentially determined by the maximum amount of time that it 
might take the microcontroller to do all of the operations associated with 
transmitting one bit and receiving one bit . This must be done within the time 
between timer interrupts. 

When both transmit and receive operations are scheduled for the same timer 
interrupt, priority is given to the transmitter routine. The reason for this 
is that a great deal of jitter can be tolerated in the timing of the received 
bit sampling, but the transmitted data must "look" good to the outside world. 

The actual bit times for transmit and receive are counted by the variables 
TxCnt and RxCnt, respectively. When an active sub-bit time slice occurs, these 
variables tell the transmit and receive routines what to do in the current 
time slice. The value 11 hex indicates a start bit, 10 hex indicates a stop 
bit, and the values 8 through F hex indicate a data bit. The values were 
chosen to allow quick determination of the appropriate action by the code. 

The routines provide for a small amount of data buffering for both the 
transmitter and the receiver. As implemented here, the transmitter buffer is 
only one byte deep, allowing one data byte to be held while another is being 
transmitted. The receiver buffer is larger, allowing three bytes to be held 
while a fourth is being received. If the receiver buffer fills up (indicated 
by the flag RxFull), the application code must retrieve one byte before a 
fourth one finishes, or data will be lost. If this happens, a flag will be set 
(OverrunErr) to indicate that the receiver buffer has been overrun. There is 
no similar flag for the transmitter, since the transmit request routine waits 
for the transmitter buffer to be available (indicated by the TxFull flag) 
before taking action. It is up to the application code to check this flag in 
advance if it does not want to stall execution while waiting to transmit data. 

As each routine finishes a whole data byte by completing the send or receive 
of a stop bit, it checks to see if there is something still happening to 
warrant having the time slice interrupt running. In the case of a received 
stop, the transmit activity flag (TxOn) is examined. If it is not set, the 
timer is turned off. The timer will be turned back on if an interrupt from a 
serial start bit is received or the main code requests data to be transmitted. 
In the case of a transmitted stop, both the receiver activity flag (RxOn) and 
the transmit buffer flag (TxFull) are examined. If the receiver is active or 
there is more data to transmit, leave the timer is left running. 

All of the status flags are in the "Flags" register. Other status flags found 
there are: RxAvail, which indicates that the receiver buffer contains 
unprocessed data; and FramingErr which is set when the receiver routines find 
an improper start or stop bit, usually caused by mismatched baud rates. 

Flow control handshaking is provided by the RTS/CTS scheme. The transmit 
routine looks at the incoming CTS line before beginning each start bit 
transmission, and simply exits, waiting for the next time slice, if CTS is not 
asserted. The receive routine checks the buffer status whenever a start bit 
interrupt occurs and de-asserts the outgoing RTS line if the buffer already 
contains two bytes (i.e., it will be full when the current byte finishes). If 
the device at the other end of the communication line follows the same rules 
(which may very well NOT be the case) the program should be able to 
communicate without buffer overflows in either direction. 

Baud rates in both the send and receive routines are determined by two things: 
the timer interrupt rate; and the number of time slices per bit. The method of 
calculating the timer value for various baud rates is discussed in the code 
listing at the BaudRate routine. This discussion has centered on there being 
four time slices per bit, but if the user wants, set either the transmitter or 
the receiver can be set to run at a baud rate that is a multiple of the other 
by adjusting the value of the constant TxBitLen or RxBitLen. The baud rate 
would be calculated as indicated for the faster channel, and TxBitLen or 
RxBitLen would be changed for the slower channel. For example, the transmitter 
can be set to run at half of the receiver baud rate by setting TxBitLen to -8 
+ 1. 

The routines shown also make provision for changing the baud rate "on the 
fly", although the application code given does not implement this feature. If 
the application code changes the baud rate for some reason, the change will be 
effected when the next data transmission or reception begins, if both the 
transmitter and receiver were already idle. This prevents the timer value from 
being changed in the middle of a data byte. 


THE CODE

There are a number routines in the code that the user should be aware of:

  Intr0     - Called (by interrupt) when a serial start bit is  received.
  Timer0    - Called (by interrupt) for every sub-bit time slice.
  RS232TX   - Called by Timer0 when the transmitter has business to conduct in 
                the current time slice.
  RS232RX   - Called by Timer0 when the receiver has business to conduct in 
                the current time slice.
  BaudRate  - Sets the baud rate variables BaudHigh and BaudLow based on the 
                accumulator value.
  TxSend    - Called by the application code to request that a data byte be 
                transmitted. The data to be transmitted is in the accumulator. 
  GetRx     - Called by the application code to request return of a received 
                data byte from the buffer. Data is returned in the 
                accumulator. This routine should not be called unless the 
                receiver buffer has data available. 
  Reset     - Start of the initialization code to set up the UART.
  MainLoop  - Start of the mainline code of the demo application.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -