assembly - PIC interrupt based soft UART timing trouble -
i've tried implement software uart on pic 18f452 using timer interrupts - although i'm begginer microcontrollers - , can't timing working. i'm using mplab asm compilation , pickit 2 programming.
list p=18f452 include <p18f452.inc> config wdt=off, lvp=off, osc=hs, cp0=off variable cyclesperbaud=1 ; 1 cycle(s) per baud variable cyclesint=0xffff ; counter in 16 bit timer variable freq = 20000000 ; clock frequency 20mhz variable baud = 9600 ; baud rate variable cyclesmain=33 ; cycles in main program branch (intr->checkbitcounter->startstopbit->transfer) variable cyclesidle=16 ; cycles in idle branch (intr->idle) variable offset = (freq/(4*baud))/(cyclesperbaud) variable initoffset = cyclesint - offset variable durroffset = cyclesint - offset + cyclesmain variable hurroffset = cyclesint - offset + cyclesidle cblock 0x20 char ; character send bitcounter ; bits left send startstopbit ; checks send start of stop bit buffer ; buffer char rotated cycle ; current cycle in cyclesperbaud starting high endc org 0000h goto main org 0008h goto intr main bcf osccon, scs ; use primary clock bsf rcon, ipen ; enable priority levels ; interrupt config: bsf intcon, gieh ; enable high priority interrupts bcf intcon, giel ; disable low priority interrupts bsf intcon, tmr0ie; enable tmr0 interrupts bcf intcon, int0ie; dis. ext. interrupts bcf intcon, rbie ; dis. rb port change int. bcf intcon, tmr0if; clear tmr0 intr. flag bit bcf intcon, int0if; bcf intcon, rbif ; bsf intcon2, tmr0ip; set tmr0 high priority ; timer 0 config: bcf t0con, tmr0on ; temp. disable timer bcf t0con, t08bit ; 16 bit counter bcf t0con, t0cs ; t0cki pin input source bcf t0con, t0se ; switch on falling edge bsf t0con, psa ; disable prescaler bcf t0con, t0ps2 ; doesn't matter bcf t0con, t0ps1 ; -||- bcf t0con, t0ps0 ; -||- ; init output registers , variables clrf trisd clrf latd movlw 0xff movwf portd ; our output port set high (serial 0 - not sure that) movlw b'01111111' ; symbol send movwf char movlw cyclesperbaud movwf cycle ; unused clrf bitcounter ; zeros clrf startstopbit ; zeros clrf buffer ; zeros ; eof init movlw low initoffset ; dunno why high has reversed low movwf tmr0h movlw high initoffset movwf tmr0l bsf t0con, tmr0on ; turn on timer loop goto loop ; waiting interrupt intr ; main branch: 8 cycles btfss intcon, tmr0if retfie bcf t0con, tmr0on ; had comment section out - didn't want work - dunno why ; decf cycle, f ; btfss status, z ; goto idle ; movlw cyclesperbaud ; movwf cycle checkbitcounter ; branches until 'tmr_ret': 16 cycles movf bitcounter, f btfss status, z goto rotatebuffer ;startstopbit movf startstopbit, f btfss status, z goto stopcopy movlw 0x8 movwf bitcounter movf char, w movwf buffer rlncf buffer, f movlw 0x00 transfer movwf portd decf bitcounter, f btfsc status, z incf startstopbit, f tmr_ret ; 5 cycles (+8 intr = 13 cycles) movlw low durroffset ; dunno why high has reversed low movwf tmr0h movlw high durroffset movwf tmr0l bsf t0con, tmr0on retfie stopcopy clrf startstopbit movlw 0xff nop goto transfer rotatebuffer rrncf buffer, f movf buffer, w nop nop nop nop goto transfer idle ; 5 cycles (+7 intr = 12 cycles) movlw low hurroffset ; dunno why high has reversed low movwf tmr0h movlw high hurroffset movwf tmr0l bsf t0con, tmr0on retfie end so i'm wondering doing wrong? mean pic sending stuff on portd, 0 it's supposed it's not data it's supposed sending. when peak transmitted (with realterm), byte being sent 11011111 or 10111111 , 11111111 instead of 01111111.
i'm guessing i'm missing timings not sure what?
also since started using 'variables' in code noticed had copy lower part off timing offsets high , high bytes low tmr0h:l registers - knows why works way? maybe i'm confusing significance of these registers: used them before if tmr0h register hold more significant 8 bits of 2 byte counter - correct?
anyway, i'd appreciate help. thanks, drinker
Comments
Post a Comment