ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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