DSPRelated.com
Blogs

Implementing a full-duplex UART using the TMS320VC33 serial port

Manuel HerreraMarch 16, 20112 comments

Although the TMS320VC33 serial port was designed to be used as a synchronous port, it can also be used as an asynchronous port under software control. This post describes the hardware and software needed to use a TMS320VC33 serial port as a full-duplex UART port. A schematic diagram and a lengthy code listing are provided to illustrate the solution. This note discusses the implementation of an interrupt-driven, full-duplex, asynchronous serial interface, 9600-baud UART with 8 data bits, 1 stop bit, and no parity using the on-chip resources of the TMS320VC33.

How do I develop a full-duplex, universal asynchronous receive transmit serial interface using the on-chip serial port of the TMS320VC33?

By using the DR0, DX0 pins in conjunction with serial port receive/transmit timers and an external interrupt, one can develop a very flexible full-duplex UART in software, as shown in Figure 1.

This design relies on the fact that received RS-232 signals always start with a “start bit” that is not part of the data, and end with one or more “stop bits” that are also not part of the data. This design keeps the receiver turned off and an interrupt (also tied to the receive line) turned on when not receiving a character.

The receive sequence begins when the start bit triggers the external interrupt. At the interrupt service routine, c_receive0, the code turns the interrupt off and the receiver on. Then the CPU samples DR0; the data comes in as a normal 8-bit character.

When serial data is input, the receiver shifts the bits into the receive-shift register (RSR). When the specified number of bits are shifted in, the data-receive register (DRR) is loaded from RSR, and the RRDY status bit is set.

After the received byte is processed, the external interrupt is then re-enabled and the system waits for the next start bit.

The stop bits assure the TMS320VC33 has time to handle the data before the next character.

The transmitter basically frames the data into 8-bit words, adding a start bit, the character to send, and the stop bit.  The transmitter then waits until it is free, after which it sends the data. The serial port is set up as a continuous transmit normal port. Frame syncs are not used and internal clocks are used for the serial port timing; these are timed with the TMS320VC33 clock and need to be adjusted if clock rates change.

A more efficient (but more complicated) design definitely could be done.

Schematic diagram for serial communication.

Figure 1. Note that the received signal is tied to DR0 (Data Receive) and also INTx (any of the TMS320VC33 interrupts). The clocks and frame syncs are not used.

Code

gl_prt_cnt    .word 068004c4h           ; Initial setup for the serial port

; status register. This sets the

; following things:

; FSX is output.

; Fixed data rate signalling

; Standard frame sync mode

; Internal xmit clk

; Internal rec clk

; Active high DX and DR

; XLEN - 8 bits

; RLEN - 8 bits

; Transmitter interrupt enabled

; Receive interrupt enabled

; Activate the transmitter

; Deactivate the receiver

x_prt_cnt     .word 00000111h           ; Setup for the transmit port control

; register. Set all the transmit

; pins as serial port pins.

r_prt_cnt     .word 00000111h           ; Setup for the receive port control

; register. Set all the receive

; pins as serial port pins.

tmr_cnt       .word 0000003cfh           ; Setup for the timer control reg.

; Starts the timer

; Free run the timer (no hold)

; Clock mode

; Internal clock source

tmr_per       .word 028b128b1h           ; Timer periods. This is 10417 for

; the receiver, which is a little

; slow. This makes sure we don’t

; shift in time before the bits.

; These also assume a 150MHZ clock

; in the VC33; these values will have

; to be adjusted for different clock

; rates.

enab_int      .word 000000031h           ; Enable serial xmit, serial recieve,

; and int 0 for serial port stuff.

first_xmt     .word 00000ffffh

rec_ser_cnt   .word 808040h              ; Address of serial port status register

s_recc_int    .word 000000001h           ; Mask for the receive interrupt (int0)

c_recc_int    .word 0fffffffeh           ; Inverted mask to clear the rec int (int0)

reset_rec     .word 0f7ffffffh           ; Mask to write a 0 to the rec reset

unreset_rec   .word 008000000h           ; Unreset the receiver.

.text

_init_io

LDP @rec_ser_cnt,DP

LDI @rec_ser_cnt,AR0

LDI @x_prt_cnt,R0           ; Set up the transmit control port.

STI R0,*+AR0(2)

LDI @r_prt_cnt,R0           ; Set up the receive control port.

STI R0,*+AR0(3)

LDI @tmr_per,R0             ; Set the timer period register.

STI R0,*+AR0(6)

LDI @tmr_cnt,R0             ; Set the timer control register.

STI R0,*+AR0(4)

LDI @gl_prt_cnt,R0          ; Set the global serial control register.

STI R0,*+AR0(0)

OR 2000h,ST                 ; Enable CPU interrupts globally

OR @enab_int,IE             ; Enable interrupts.

LDI @first_xmt,R0           ; Start the transmitter sending 1’s

STI R0,*+AR0(8)

RETS


;* c_sp0intTra -     handle an interrupt from the serial port transmitter.

c_sp0intTra

PUSH R0

PUSH DP

PUSH AR0

 

CALL _flip8                ; data to be transferred to serial port is

; supposed to be already loaded in R0

              STI R0,*+AR0(8)

 

POP AR0

POP DP

POP R0

POP ST

RETI

 

;* c_int0Rec -   This interrupt handle is called by INT0. It is tied to the

;*               receive data line, it will be called when the start bit is received

;*               for a character of information. It will turn on the serial receiver

;*               (and the serial receiver interrupt) and turn its own interrupt off.

c_int0Rec

PUSH ST

PUSH R0

PUSH DP

PUSH AR0

 

LDP @rec_ser_cnt,DP        

LDI @rec_ser_cnt,AR0

 

AND @c_recc_int,IE          ;do not allow the receive coming interrupt

 

LDI *+AR0(0),R0             ;Ready the receiver

OR @unreset_rec,R0

STI R0,*+AR0(0)

 

POP AR0

POP DP

POP R0

POP ST

RETI

;* c_sp0intRec - Handle an interrupt from the serial port receiver to inform it

;*               of the receipt of a byte on the serial port. This routine will

;*               turn off the receiver and restore the interrupt telling it that

;*               a byte is about to come.

c_sp0intRec

PUSH ST

PUSH R0

PUSH DP

PUSH AR0

 

LDP @rec_ser_cnt,DP

LDI @rec_ser_cnt,AR0

 

LDI *+AR0(0),R0             ;Reset the receiver

AND @reset_rec,R0

STI R0,*+AR0(0)

AND @c_recc_int,IF          ;clear receive coming interrupt

OR @s_recc_int,IE           ;enable the interrupt for the next byte

 

LDI *+AR0(0xC),R0           ;data received at 0x80804c

CALL _flip8                 ;data from RS-232 is backwards, flip it around

 

POP AR0

POP DP

POP R0

POP ST

RETI

 

This code assumes all interrupts services routines are installed.


Reference

[1] "TMS320C3x User’s Guide". Texas Instruments. Julio 1997-SPRU031E.

[2] "TMS320C3x General-Purpose Applications". Texas Instruments. Julio 1997-SPRU194.



[ - ]
Comment by manuelonJune 6, 2011
Sure. I hope I can help.
[ - ]
Comment by deepak55April 1, 2011
nice job!!!. I am doing one project but facing some problem to change my C codes to tms320dm processor...so is it possible for you to heip me somehow???

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: