Serial Communications Demo: Transmitting from the SCI
;****************************************************************
;*
;* UTEP EE3376
;* sci_demo.asm
;* 15 July 2005
;*
;* This program uses the SCI1 serial port to transmit (TX) and
;* receive (RX) a string of data at 9600 baud. The program runs
;* in an infinite loop, transmitting and receiving characters
;* at the same time (with a 2 msec delay between TX and RX frames).
;*
;* NB: For the Dragon12 board, you MUST set jumper J23 to positions
;* 1-2 (URXD1) to connect PS2 header pin to pin P91 of the HCS12.
;*
;*
;* Program can be tested in two modes:
;* Single board mode: connect PS3 (TX) to PS2 (RX) with short jumper cable.
;* Two board mode: connect VSS2 (grd) of board 1 to VSS2 of board 2
;* and then connect PS3 (TX) of board 1 to PS2 (RX) of board 2.
;* For either, you can use DBug12 "md 2000" to see the TX and RX strings.
;*
;* -- only TX code shown, and there is an intentional error in setting up tx_ptr
;* -- RX code must be added if needed
;*
;****************************************************************
; export symbols
XDEF Entry ; export 'Entry' symbol
ABSENTRY Entry ;mark this as application entry point
PSEUDO_ROM EQU $1000 ; absolute address to place code/constant data
RAM EQU $2000 ; absolute address to place variables
STACK EQU $3C00 ; top of stack
; SCI registers - not all are used in program
sci1bdh EQU $00D0 ; SCI1 Baud Rate Generator, high byte
sci1bdl EQU $00D1 ; SCI1 Baud Rate Generator, low byte
sci1cr1 EQU $00D2 ; SCI1 Control Register 1
sci1cr2 EQU $00D3 ; SCI1 Control Register 2
sci1sr1 EQU $00D4 ; SCI1 Status Register 1
sci1sr2 EQU $00D5 ; SCI1 Status Register 2
sci1drh EQU $00D6 ; SCI1 Data Register, high byte
sci1drl EQU $00D7 ; SCI1 Data Register, low byte
; masks
enableTX EQU $08 ; mask to enable TX
; constants and mnemonics
br9600 EQU $9C ; BR to set Baud Rate to 9600, 24 MHz clock
msec EQU $1770 ; 6000 (=$1770) loops = 1 msec in startx loop
;-----------------------------------------------------
; variable/data section
ORG RAM
tx_string dc.b "El Paso"; the string we will output via TX
tx_ptr ds.w 1 ; ptr to position in tx_string
;------------------------------------------------------
; code section
ORG PSEUDO_ROM ;set PC to $1000
Entry:
lds #STACK ; initialize stack
movb #br9600,sci1bdl ; set BAUD rate to 9600
movb #enableTX, sci1cr2 ; enable TX
; loop2 is an infinite loop that resets ptrs and runs loop1
loop2: ldaa #$07 ; number characters in tx_string
movw tx_string, tx_ptr ; initialize tx_ptr ->there is an error here!
; infinitely output tx_string
loop1: ldx tx_ptr
jsr TX_CHAR ; output char via TX of SCI1
jsr DELAY ; wait 2 msec between TX
inx ; update tx_ptr lower byte
stx tx_ptr
deca
bne loop1
bra loop2 ; infinite loop
swi ; end the program
;------------------------------------------------------
; Subroutine TX_CHAR
; TX a character from the SCI1 interface
; char resides in TX string at address pointed to by X register
; the terminology ($2000) refers to the contents of address $2000
; so ((X)+0) refers to the contents of address in X + 0, eg ($2000 + 0)
; to send contents of an address in X to sci1drl, we must use the 0,x type offset indexed addressing
TX_CHAR:
spin1: brclr sci1sr1, #$80, spin1 ; wait till TDRE set
movb 0,x, sci1drl ; send ((X)+0) to TX data reg.
rts
;------------------------------------------------------
; Subroutine DELAY - y contains number of Delay loops
; 1 msec delay per Delay loop
DELAY:
pshy
pshx
ldy #$02
starty: ldx #msec
startx: dex
bne startx
dey
bne starty
pulx
puly
rts
;****************************************************************
* Create a new project called "sci_demo" using ee3376 stationery. Cut and paste the code above into a program called "sci_demo.asm" and call the executable "sci_demo.abs.s1".
* Note that there is one subtle mistake in the code concerning how tx_ptr was set up. Look in the "movw tx_string, tx_ptr" statement and think about what value you are really sending to the tx_ptr. Note that tx_string is a synonym for the number $2000, and tx_ptr is a synonym for the number $2007, so the statement is the same as "movw $2000, $2007". Do you want to send the contents of address $2000 or the address $2000 itself to tx_ptr? Correct the mistake and assemble the code.
NOTE: Mistaking the contents of a pointer with a pointer itself (remember, a pointer is an address) is a VERY common error in embedded programming. When you have unusual errors in your programs, try checking that you didn't mistake a pointer for the contents of a pointer or vice versa.
* Hook up a LA2124 logic analyzer to the Dragon12 board. Connect the VSS2 (ground) pin of the Dragon12 to the ground pin of the LA2124, and connect the TX header pin labelled PS3 on the Dragon12 to the channel 0 pin of the logic analyzer. Set the logic analyzer to trigger on Channel 0 logic 0, and set the trigger mode to single. Set the clock to 100 khz (10 usec). Keep the logic analyzer window open. See the logic analyzer demo for a review of how to use the logic analyzer if needed.
* Load the sci_demo.abs.s1 program into the Dragon12 but do NOT start it yet. Go to the logic analyzer window and click on the "Go" description button to start the logic analyzer. Since the TX pin is high and the logic analyzer triggers on a low (logic 0), the logic analyzer will just sit there and wait until the TX pin goes low. Once we start the program on the Dragon12 board and the TXD1 pin goes low, then the logic analyzer will trigger and we will thus capture our first transmission. The trigger is set to "single", so we will only capture this first transmission event.
* Start the sci_demo.abs.s1 program by typing in "g 1000" at the DBug12 prompt. The program will run in an infinite loop until we stop it with the yellow abort button on the Dragon12. Once the program starts, the logic analyzer will trigger and capture the few signals sent out from the TXD1 pin on the Dragon12. Below is a screenshot of what the logic analyzer capture looks like:
* Verify that your screenshot looks like that above. You should be able to decode the first few character frames (zoom in if you need to). Note that the actual waveform you see will depend on which string position you captured using the logic analyzer (the string is output in an infinite loop again and again; you may be seeing the "E" or the "a" character of "El Paso", depending on where the string output is when you capture it). In any case, when you decode the waveform, you should get a character which is part of the string "El Paso". If your program did not produce the expected output, go check your code, esp. the tx_ptr setup, and correct it as necessary.
* You can click on the abort button on the Dragon12 to stop the program. To rerun the program from the beginning, hit the reset button of the Dragon12 to reset the program. Hit the "Go" button once on the logic analyzer to arm it for the next capture, and then type in "g 1000" at the DBug2 prompt.
* Your program should run OK if you have followed the above instructions and corrected the pointer mistake noted above. If you are having problems, ask the TA for assistance.