;;*************************************** ;;***** RS-232 test on 4114 ************* ;;*************************************** ;Fully interrupt driven ;Strings can come from flash or RAM. .include "d:\bruce\atmel\asm src\4414def.inc" .device AT90S4414 .def temp =r16 ;temporary register .def count =r17 ;a counter to use in message .def savSREG =r18 ;save the status register .def TXbusy =r19 ;transmit busy flag .def RXchar =r20 ;a received character .def TXflash =r21 ;text to be sent is in flash if <>0 .equ baud96 =25 ;9600 baud constant for 4Mhz crystal .equ go ='g' ;0x67 ascii 'g' .equ stop ='s' ;0x73 ascii 's' .equ azero ='0' ;0x30 ascii '0' ;************************************** .dseg ;define variable strings to be tranmitted from RAM cntstr: .byte 3 ;a two digit count + a zero terminate ;************************************** .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti reti reti reti reti rjmp RXdone ;UART receive done rjmp TXempty ;UART buffer empty rjmp TXdone ;UART transmit done reti ;define fixed strings to be tranmitted from flash- zero terminated text: .db "The count is:",0x00 crlf: .db 0x0d, 0x0a, 0x00 ;carrage return/line feed RESET: ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ;initial conditions ldi count,azero ;ascii zero the count clr TXbusy ;start out not busy on TX ldi RXchar, go ;start out running ;setup UART -- enable TXempty & RXdone int, and RX, TX pins ldi temp, 0b10111000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ;intialize text pointer BEFORE turning on interrupts ;because RESET causes the TX empty flag to be SET ldi ZL, LOW(crlf<<1) ;do shift to convert word-addr to byte ldi ZH, HIGH(crlf<<1) sei ;now print three strings and wait for incoming character interrupt TXloop: cpi RXchar, go ;wait for go signal - a 'g' on the keyboard brne TXloop ;undate counter and form string in RAM inc count ;a counter to append to message cpi count, 10+azero ;only counts to 9 then resets to brlt noreset ;ascii zero ldi count, azero noreset:ldi ZL, LOW(cntstr) ;ptr to RAM ldi ZH, HIGH(cntstr) ldi temp, azero ;leading zero to write to RAM st Z, temp inc ZL ;the count byte to write to RAM st Z, count inc ZL ;zero string terminator to RAM clr temp st Z, temp ;set up the transmit pointer for the first message ldi ZL, LOW(text<<1) ;shifted becuase pgm memory is words ldi ZH, HIGH(text<<1) ; lpm ;put the char in r0 out UDR, r0 ;put the character in the UART buffer ser TXflash ;string is in flash memory ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait ;chill until done ;now the pointer to the variable message in RAM ldi ZL, LOW(cntstr) ;ptr to RAM ldi ZH, HIGH(cntstr) ld r0,Z out UDR, r0 ;fire off the UART transmit clr TXflash ;the string is in RAM ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait ;setup ptr for string ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory is words ldi ZH, HIGH(crlf<<1) lpm out UDR, r0 ;trigger the UART TX ser TXflash ;text string in flash memory ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait rjmp TXloop ;***************************** ;interrupt routines ; UART needs a character TXempty:in savSREG, SREG ;save processor status tst TXflash ;Is the string in flash memory? breq TXram ;If not, it is in RAM inc ZL ;get the next char from flash lpm ;and put it in r0 rjmp TXfls TXram: inc ZL ;get the next char from RAM ld r0,Z TXfls: tst r0 ;if char is zero then exit breq TXend out UDR, r0 ;otherwise transmit it rjmp TXexit ;exit until next char TXend: clr TXbusy ;no more chars cbi UCR, UDRIE ;clear the TXempty interrupt TXexit: out SREG, savSREG ;restore proc status reti ;back to pgm ; TX done -- buffer is empty -- unused here TXdone: in savSREG, SREG ;save processor status out SREG, savSREG ;restore proc status reti ;back to pgm ; UART read a character RXdone: in savSREG, SREG ;save processor status in RXchar, UDR ;get the character out SREG, savSREG ;restore proc status reti ;back to pgm ;***************************** ;subroutine TXwait: tst TXbusy ;now wait for the tranmission to finish brne TXwait ret