;;*************************************** ;;***** RS-232 test on 8515 ;;***** with number parser ;;*************************************** ;Polled -- no interrrupts ;Strings can come from flash or RAM. ;input a string, then output it again ;if the string has two numbers, then parse them ;into two register num1 and num2 .include "d:\bruce\eedocs\atmel\asm src\8515def.inc" .device AT90S8515 .def char =r0 ;character to send/receive .def ccount =r1 ;number of chars in a token .def valueL =r2 ;parsed number .def valueH =r3 .def temp =r16 ;temporary register .def TXflash =r17 ;text to be sent is in flash if <>0 .def nextc =r18 ;parser character .def num1 =r19 .def num2 =r20 .equ baud96 =25 ;9600 baud constant for 4Mhz crystal .equ azero ='0' ;0x30 ascii '0' ;************************************** .dseg ;define variable string to be stored/transmitted in RAM StrBuffer: .byte 32 ;a string buffer StrToken: .byte 4 ;token buffer ;************************************** ;print and read string macros .macro PrintFlashStr ;use: PrintFlashStr flashaddress ldi TXflash, 1 ldi ZL, low(@0<<1) ldi ZH, high(@0<<1) rcall putString .endmacro .macro PrintRamStr ;use: PrintRamStr ramaddress ldi TXflash, 0 ldi ZL, low(@0) ldi ZH, high(@0) rcall putString .endmacro .macro ReadStr ;use: ReadStr ramaddress ldi ZL, low(@0) ldi ZH, high(@0) rcall getString .endmacro ;************************************** ;multiply macros .macro mult10 ;use: mult10 valueL valueH push ZL push ZH lsl @0 ;mult by two rol @1 mov ZL,@0 ;make a copy of 2*num mov ZH,@1 lsl @0 ;mult by four rol @1 lsl @0 rol @1 add @0, ZL ; 2*num+8*num = 10*num adc @1, ZH pop ZH pop ZL .endmacro ;************************************** .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti reti reti reti reti reti reti reti reti ;define fixed strings to be tranmitted from flash- zero terminated prompt: .db "Enter two numbers>",0x00 echo: .db "The string was>",0x00 nums: .db "The numbers in HEX were>",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 ;setup UART -- enable RX, TX pins ldi temp, 0b00011000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp sei ;now print a prompt and wait for incoming string with loop: ;print a prompt and wait for incoming string with PrintFlashStr crlf PrintFlashStr prompt ;read the string and echo it ReadStr StrBuffer PrintFlashStr echo PrintRamStr StrBuffer PrintFlashStr crlf ;determine the numbers rcall parse PrintFlashStr nums ;convert num1 to hexadecimal mov temp, num1 rcall reg2hex PrintRamStr StrBuffer ldi temp, ' ' ;insert a space mov char, temp rcall putc ;convert num1 to hexadecimal mov temp, num2 rcall reg2hex PrintRamStr StrBuffer PrintFlashStr crlf rjmp loop ;********************************************* ;string soubroutines ;********************************************* ;routine to output one char ;enter with char in char putc: sbis USR, UDRE ;wait until clear then send one char rjmp putC out UDR, char ret ;routine to input one char ;exit with char in char getc: sbis USR, RXC ;wait until ready then get one char rjmp getc in char, UDR ret ;routine to send a string putString: tst TXflash ;is it flash? breq _txram lpm ;char ;if so get a char rjmp _tstend _txram: ld char, Z ;if mem get a char _tstend:tst char ;is it string end marker? breq _TXend rcall putc ;emit a char adiw ZL, 1 ;set up next pointer rjmp putString _TXend: ret ;routine to read a string getString: rcall getc rcall putc ;echo it ldi temp, 0x0d ;a cp char, temp ;carriage return? breq _RXend st Z+, char ;store the char rjmp getString _RXend: ldi temp, 0 ;append a 0x00 to string st Z, temp ldi temp, 0x0a ;line feed makes terminal nicer mov char, temp rcall putc ret ;****************************************** parse: ldi ZL, low(StrBuffer) ldi ZH, high(StrBuffer) push YH push YL ;get the first number rcall token rcall convert mov num1, valueL ;get the second number rcall token rcall convert mov num2, valueL ;clean up and return to command stuff pop YL pop YH ret ;exits with one token in StrToken and char count in ccount token: ldi YL, low(StrToken) ldi YH, high(StrToken) clr ccount _notnum:ld nextc, Z+ cpi nextc, '0' brlt _notnum cpi nextc, ':' ;just above 9 brge _notnum ;if get here then we have a digit char ;loop until we hit a non-digit _isnum: st Y+, nextc inc ccount ld nextc, Z+ cpi nextc, '0' brlt _tdone cpi nextc, ':' ;just above 9 brge _tdone rjmp _isnum _tdone: ret ;enters with a token in StrToken and a char count in ccount ;exits with a numerical value in valueH/L convert:ldi YL, low(StrToken) ldi YH, high(StrToken) clr valueL clr valueH clr temp _cnext: ld nextc, Y+ subi nextc, '0' ;convert ascii to a digit add valueL, nextc ;and add it to value adc valueH, temp dec ccount breq _cdone mult10 valueL, valueH rjmp _cnext _cdone: ret ;****************************************** reg2hex:ldi ZH, high(StrBuffer) ldi ZL, low(StrBuffer) push temp ;make a copy andi temp, 0xf0 ;mask high digits swap temp ;and make them loworder cpi temp, 10 ;numbers or letters? brge _f8f1 subi temp, -'0' ;convert a numeric digit to ascii rjmp _f8tx1 _f8f1: subi temp, -'a'+10 ;convert a letter to ascii _f8tx1: st Z+, temp pop temp ;now repeat for the other digit andi temp, 0x0f cpi temp, 10 brge _f8f2 subi temp, -'0' rjmp _f8tx2 _f8f2: subi temp, -'a'+10 _f8tx2: st Z+, temp ldi temp, 0 ;zero terminator st Z+, temp ret