;;*************************************** ;;***** RS-232 test on 4114 ************* ;;*************************************** ;Fully interrupt driven ;Strings can come from flash or RAM. .include "c:\tmp\8535def.inc" .def ascii_1 =r1 .def ascii_2 =r2 .def ascii_3 =r3 .def LF =r4 .def CR =r5 .def NULL =r6 .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 .def ADCvalc =r22 .def temp2 =r23 .def count_L =r24 .def count_H =r25 .equ baud96 =51 ;9600 baud constant for 4Mhz crystal .equ go ='g' ;0x67 ascii 'g' .equ stop ='s' ;0x73 ascii 's' .equ azero ='0' ;0x30 ascii '0' .equ counts =300; ;************************************** .dseg ;define variable strings to be tranmitted from RAM cntstr: .byte 3 ;a two digit count + a zero terminate ADCvals:.byte counts ;300 consecutive ADC values ;************************************** .cseg .org $0000 rjmp RESET ;reset entry vector reti ;Ext int req0 reti ;Ext int req1 reti ;Timer/Counter2 compare match reti ;Timer/Counter2 Ovfl reti ;Timer/Counter1 Capture event rjmp cp_match;Timer/Counter1 Compare match A reti ;Timer/Counter1 Compare match B reti ;Timer/Counter1 Ovfl reti ;Timer/Counter0 Ovfl reti ;Serial Transfer Complete reti ;UART receive done rjmp TXempty ;UART buffer empty reti; ;UART transmit done reti ;ADC conversion complete reti ;EEPROM ready reti ;Analog comparator ;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 ;set up port B to run LEDS ser temp ;set PORTB to be out DDRB,temp ;all outputs to LEDs out PORTB, temp out DDRC, temp out PORTC, temp ;clear ADCval register clr ADCvalc ;set up analog converter to read channel zero ldi temp, 0 out ADMUX, temp ;enable and set up ADC ;prescaler = 64 ;ADC free run mode disbaled ;ADC start conversion off (turn on when ready) ldi temp, 0b10000110 out ADCSR, temp ;start the ADC initalization ldi temp, 0b01000000 ;start A to D conversion in temp2, ADCSR or temp, temp2 out ADCSR, temp ;spin until the ADC is finished rwait: in temp, ADCSR ;wait for A to D done sbrc temp, 6 ;by checking ADSC bit rjmp rwait ;this bit is cleared by the AtoD hardware clt ;clear t bit ;wait for press clr temp ;set PORTB to be out DDRD,temp ;all inputs in temp, PIND ;IN to PINs OUT to PORTs ldi temp, 0xAA out PORTB, temp butt_wait: sbic PIND, 0 ; check buttons, set state rjmp butt_wait ldi temp, 0x00 out PORTB, temp ;set up timers and match register ;enable compareA match register int ldi temp, 0b00010000 out TIMSK, temp ;set match regs for fs=3000hz (2667ticks for fs=2999.6) ldi temp, 0x0A ;set the match A register to out OCR1AH, temp ; ldi temp, 0x6B ;2667 = 0x0A6B out OCR1AL, temp ;set prescaler to 1 and clear on compare/match ldi temp, 0b00001001 out TCCR1B, 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, 0b00001000 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(ADCvals) ;do shift to convert word-addr to byte ldi ZH, HIGH(ADCvals) sei ;capture 300 samples with ADC and place in SRAM clr count_L clr count_H await: brtc await ;wait if t bit is cleared in temp, ADCSR ;wait for A to D done out PORTC,temp sbrc temp, 6 ;by checking ADSC bit rjmp await ;this bit is cleared by the AtoD hardware clt ;clear the t bit in the status register in temp, ADCL ;read the voltage in temp2, ADCH lsr temp2 ;double precision shift ror temp ;right twice lsr temp2 ror temp mov ADCvalc, temp st Z+, ADCvalc ;st Z+, count_L ldi temp, 1 add count_L, temp clr temp adc count_H, temp cpi count_L, LOW(counts) brne await cpi count_H, HIGH(counts) brne await ;we're done!!! stop the clock to prevent futher ADC samples ;set prescaler to 1 and clear on compare/match ldi temp, 0b00001000 out TCCR1B, temp ldi ZL, LOW(ADCvals) ldi ZH, HIGH(ADCvals) clr count_L clr count_H ;300 vals now in SRAM, time to send 'em to the UART!!! write_all: ld ADCvalc, Z+ clr ascii_1 clr ascii_2 clr ascii_3 start_divide: cpi ADCvalc,100 brlo hundreds_done inc ascii_1 subi ADCvalc,100 rjmp start_divide hundreds_done: cpi ADCvalc,10 brlo tens_done inc ascii_2 subi ADCvalc,10 rjmp hundreds_done tens_done: cpi ADCvalc,1 brlo divide_done inc ascii_3 dec ADCvalc rjmp tens_done divide_done: mov temp, ascii_1 subi temp,-azero mov ascii_1,temp mov temp, ascii_2 subi temp,-azero mov ascii_2,temp mov temp, ascii_3 subi temp,-azero mov ascii_3,temp ldi temp,0x0d mov CR,temp ldi temp,0x0a mov LF,temp ldi temp,0 mov NULL,temp ;now print three strings and wait for incoming character interrupt TXloop: noreset: ;set up the transmit pointer for the registers holding the ASCII digits ldi YL, 1 ;shifted becuase pgm memory is words ldi YH, 0 ; ld r0, Y ;put the char in r0 out UDR, r0 ;put the character in the UART buffer ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait ;chill until done ldi temp, 1 add count_L, temp clr temp adc count_H, temp cpi count_L, LOW(counts) brne write_all cpi count_H, HIGH(counts) brne write_all ;write out some carrige returns ldi temp, 0x0a mov r1, temp mov r2, temp mov r3,temp clr r4 ;set up the transmit pointer for the registers holding the ASCII digits ldi YL, 1 ;shifted becuase pgm memory is words ldi YH, 0 ; ld r0, Y ;put the char in r0 out UDR, r0 ;put the character in the UART buffer ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait ;chill until done ;no more to write! rjmp halt ;***************************** ;interrupt routines ; UART needs a character TXempty:in savSREG, SREG ;save processor status TXram: inc YL ;get the next char from RAM ld r0,Y 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 ;***************************** ;subroutine TXwait: tst TXbusy ;now wait for the tranmission to finish brne TXwait ret ;**** timer 1 compare A match cp_match: in savSREG, SREG ldi temp, 0b01000000 ;start A to D conversion in temp2, ADCSR or temp, temp2 out ADCSR, temp ;inc freq ;out PORTC,freq ;sets the T flag in status reg out SREG, savSREG set reti halt: rjmp RESET