ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 3108
Скачиваний: 0
3.8 Programming the Asynchronous Serial Interface |
37 |
In the operating mode 0, the interface acts like a serial shift register. The serial shift clock has a fixed frequency, equal to fosc/12. Eight data bits are transmitted, starting with the least significant bit (LSB). In mode 1, 10 bits are shifted from (to) SBUF: one start bit, eight data bits (LSB first) and one stop bit. The communication speed is variable and programmable using the system timer. In operating modes 2 and 3, nine data bits are sent, packed by a start bit and a stop bit. The communication speed is fixed in mode 3 and variable in mode 3. Modes 2 and 3 are designed for multiprocessor communication. This operating mode is specific for 8051, and will not be discussed in this book. For normal operating modes 0, 1, the SM2 bit must be cleared.
The most significant bit of SCON, FE/SM0, has a dual function. The selection between the two functions is made by the bit SMOD0, in the register PCON (Power Control Register). If SMOD0 = 1, then bit 7 (SCON) = FE, and if SMOD0 = 0, then bit 7 (SCON) = SM0. FE (Framing Error) is set if a zero is detected in the position of the stop bit while receiving a character, and cleared by writing zero to the corresponding position of SCON.
The control bit REN (Receiver Enable) is used to enable (REN = 1) or disable (REN = 0) the receiver. There is no similar bit to enable/disable the transmitter.
TB8 – RB8 contain the ninth data bit (the most significant bit, MSB) in operating modes 2 and 3.
TI (Transmit Interrupt flag) is set by hardware at the end of the transmission of a character. If the interrupt associated with the serial interface is enabled, the condition TI = 1 generates an interrupt. TI must be cleared by software by writing zero to this position of SCON.
RI (Receive Interrupt flag) is hardware set when a character has been received and is available in SBUF. If the local interrupt mask is set to 1, an interrupt is generated. RI must be cleared by writing zero to this position of SCON.
If the interrupts are disabled, TI and RI can be polled by software.
As described in Chap. 1, the interrupt system of 8051 is controlled by the IE register. For the serial communication interface, one single bit, called ES, is reserved in this register. Therefore it is not possible to enable/disable the receiver and transmitter interrupts separately.
To get the full picture on the serial communication of 8051, refer to Chap. 6 for an example on how to use the system timer as a baud rate generator.
3.8 Programming the Asynchronous Serial Interface
When programming any peripheral interface there are two major aspects to consider: the initialization of the interface, and the actual data handling. Normally, the initialization sequence is executed only once, after RESET. Data handling can be performed either by periodically testing the status bits of the interface (polling), or by enabling the interrupts associated with the interface.
This paragraph contains several examples of initialization sequences and serial communication data handling for HC11 and AVR.
38 3 Using the Asynchronous Serial Interface
3.8.1 Programming the SCI of HC11
The initialization sequence must do the following:
•Enable the transmitter and the receiver.
•Select the communication speed, by writing an appropriate value to the BAUD register.
•Enable interrupts, if this is required.
Here is an example on how to initialize the SCI of 68HC11F1 for 9600 baud, no interrupts. In this example it is assumed that the oscillator frequency is 8 MHz.
INIT_SCI |
LDAA |
#$30 |
;see paragraph |
3.5. |
STAA |
BAUD |
;9600 baud |
||
CLR |
SCCR1 |
;clear M for 8 |
bit |
|
;communication |
||||
LDAA |
#$0C |
;TE=1, RE=1 |
||
STAA |
SCCR2 |
;no interrupts |
||
.... |
And the reception and transmission routines may look like this:
SCI_REC |
LDAA |
SCSR |
;read status register |
ANDA |
#$20 |
;isolate RDRF bit |
|
BEQ |
SCI_REC |
;wait until RDRF is set |
|
LDAA |
SCDR |
;get received character |
|
STAA |
SOMEWHERE |
;and save it |
|
RTS |
|||
SCI_SEND |
TAB |
;save character to B |
|
SSLOOP |
LDAA |
SCSR |
;read status register |
ANDA |
#$80 |
;isolate TDRE |
|
BEQ |
SSLOOP |
;wait until transmitter |
|
;ready |
|||
STAB |
SCDR |
;send character |
|
RTS |
;and return |
This way of writing the SCI_REC routine is a very bad idea. It is always recommended be avoided wait loops, that when the duration of the loop is unknown. In the above example, the processor spends most of the time waiting for a character from the SCI. A much better solution would be to write the reception routine like this:
SCI_REC2 |
LDAA |
SCSR |
;read status register |
ANDA |
#$20 |
;isolate RDRF bit |
|
BEQ |
FRET |
;failure return |
|
LDAA |
SCDR |
;get received character |
|
STAA |
SOMEWHERE |
;and save it |
|
SEC |
;Set Carry to inform |
||
RTS |
;the main program |
||
FRET |
CLC |
;Clear carry |
|
RTS |
3.8 Programming the Asynchronous Serial Interface |
39 |
This time, the processor doesn’t wait indefinitely for a character. It tests from the beginning whether a character is available in SCDR, by checking the RDRF flag. If a character has been received, this is read and saved in a variable, and the carry flag is set to inform the main program about the event. If no character has been received, the carry bit is cleared. Such a reception routine must be called periodically in a program loop, but it has the advantage that the CPU does not hang up until a character is received.
An even better solution would be to use SCI reception interrupts to handle the reception of characters. For this purpose, the initialization routine must be modified to enable the interrupts generated by RDRF.
INIT_SCI |
LDAA |
#$30 |
;see paragraph 3.5 |
STAA |
BAUD |
;9600 baud |
|
CLR |
SCCR1 |
;clear M for 8 bit |
|
;communication |
|||
LDAA |
SCSR |
;clear flags if any |
|
LDAA |
SCDR |
||
CLR |
QSCI |
||
CLR |
QSCIERR |
||
LDAA |
#$2C |
;RIE=1, TE=1, RE=1 |
|
STAA |
SCCR2 |
;enable receiver |
|
;interrupts |
|||
..... |
The control word written into SCCR2 contains the RIE bit set to 1, thus enabling the reception interrupts. Note that, before enabling the interrupts, SCSR and SCDR are read in this sequence in order to clear any flag that might generate a false interrupt. QSCI and QSCIERR are two variables indicating that a character has been received, or that a communication error has been detected. The interrupt service routine looks like this:
SCI_ISR |
LDAA |
SCSR |
|
ANDA |
#$0E |
;Isolate all error flags |
|
BNE |
SCIERR |
;if error, inform the |
|
;main program |
|||
LDAA |
SCDR |
;get character |
|
STAA |
SCIRB |
;save it in a buffer |
|
INC |
QSCI |
;true QSCI |
|
RTI |
;return from interrupt |
||
SCIERR |
LDAA |
SCDR |
;read SCDR to clear flags |
STAA |
SCIRB |
||
INC |
QSCI |
;true QSCI |
|
INC |
QSCIERR |
;true error flag |
|
RTI |
Note that when a reception error occurs, it is important to read the character received to make sure that the flag that has generated the interrupt is cleared. It is seldom required to analyze what error occurred, because in most cases, the only thing to do is to ask for the character to be retransmitted.
40 3 Using the Asynchronous Serial Interface
Important note. The SCI of HC11 uses two lines of PORTD to implement the transmission and reception lines TxD, RxD. By enabling the SCI transmitter and receiver, the TxD line is automatically configured as an output line, and RxD is configured as an input line, regardless of the contents of DDRD.
3.8.2 Programming the UART of AT90S8535
Here is an example of initializing the UART of AT90S8535 for 19 200 baud, 8 bits per character, no interrupts:
.EQU |
K19200=25 |
;xtal=8 MHz |
|
;BaudRate=19200 |
|||
Init_Uart: |
|||
Ldi |
R16,K19200 |
; set baud rate |
|
Out |
UBRR,R16 |
||
Ldi |
R16,$18 |
;RXEN=1, TXEN=1 |
|
Out |
UCR,R16 |
||
Ret |
|||
To enable reception interrupts, the control word written to UCR must be modified so that the bit RXCIE = 1 (Reception Complete Interrupt Enable).
.EQU |
K19200=25 |
;xtal=8 MHz |
|
;BaudRate=19200 |
|||
Init_Uart: |
|||
Ldi |
R16,K19200 |
; set baud rate |
|
Out |
UBRR,R16 |
||
Ldi |
R16,$98 |
;RXEN=1, TXEN=1 |
|
Out |
UCR,R16 |
;RXCIE=1 |
|
Ret |
|||
Unlike HC11, AVR microcontrollers clear the interrupt flag automatically by hardware, when the interrupt is executed. The CPU status is NOT saved and restored automatically, and therefore the CPU registers used by the interrupt routine must be saved to the stack by software. Here is an example of a simple interrupt service routine for AVR:
Uart_ISR:
Push |
R16 |
;save CPU status |
In |
R16,SREG |
|
Push |
R16 |
|
In |
R16,UDR |
;get character |
Sts |
RECBUF,R16 |
;save it |
Ldi |
R16,$FF |
|
Sts |
QUART,R16 |
;true QUART |
Pop |
R16 |
;restore status |
3.8 Programming the Asynchronous Serial Interface |
41 |
|
Out |
SREG,R16 |
|
Pop |
R16 |
|
Reti |
;return to main |
QUART is a software flag that, when true, informs the main program that a character is available. RECBUF is a one-character buffer to store the character received from the UART.
3.8.3 Programming the UART of 8051
The 8051 asynchronous serial interface does not include a dedicated baud rate generator. It uses the internal timer to generate the serial clock. Refer to Chap. 6 to understand how the timer is used in the following initialization routine. The control word written to SCON selects the operating mode 1 for the serial interface, and sets the bit REN = 1 to enable the receiver subsystem.
INIT_UART:
MOV |
SCON,#50H |
;UART mode 1, REN=1 |
MOV |
PCON,#80H |
;SMOD=1 |
MOV |
TMOD,#20H |
;C/T=0, M1=1, M0=0 |
MOV |
TH1,#0FAH |
;auto reload value |
MOV |
TCON,#40H |
;TR1=1 -- start counting |
RET |
Serial interface interrupts can be enabled by setting the bit ES in the register IE. Below is an example of serial reception and transmission routines, which use RI and TI polling rather than interrupts:
GETCHR: |
|||
CLR |
C |
||
JB |
RI,GETCHR1 |
;if character received |
|
RET |
|||
GETCHR1: |
MOV |
A,SBUF |
;get it |
CLR |
RI |
;always clear flag! |
|
SETB |
C |
;inform main program |
|
RET |
|||
SENDCHR: |
|||
CLR |
C |
||
JB |
TI,SENDCHR1 |
;check if transmitter |
|
;ready |
|||
RET |
|||
SENDCHR1: |
|||
CLR |
TI |
||
MOV |
SBUF,A |
;start sending |
|
SETB |
C |
;set carry to inform main |
|
;program |
|||
RET |