Wednesday, 18 January 2012

Timer Interruptus...

Slowly but steady goes the progress.I have now added Timer 2 interrupt handler and real time (1ms accurate) clock to my code. With this timer system I don't need to use busy looping for time keeping and I can later adjust the system for other real.time needs.

There are two important key parts to consider at this version of program. The interrupt service routine and the Timer2 initialization routine.

The interrupt service routine itself consists of three parts. At beginning, it saves the W and STATUS registers so that those can be used at interrupt without distrupting the main program. I have selected unbanked RAM (at 0x70-0x7f) for storage cause those ram locations are always available. Also it's essential that these same registers are restored before returning from the interrupt handler.

Middle part of the routine looks quite a simple for now. There is just increment of the multibyte millisecond counter and reset of timer interrupt flag. This code will grow at the future depending what applications I'll make with this micro controller.

Next likely parts will be implementing interrupt based software serial port, transmitting for debug purposes. Most likely I'll use 9600bps and try to keep the code minimal. After that the next possible direction is to make test routines for the A/D converters.

After those.. I hope I'll have all the parts for an application I've been wanting to make for some time now, the parts are in Slow-mail coming from another side of the earth so there is no  telling when they manage to appear.

--- Cut here.. Code follows

; minimal -led blinker
; V2 with Timer2 interrupt

; Uses Timer2 to generate 1ms timer interrupt

;PortC pins:
; RC:0 = digital out, led active high

  #include p16f616.inc 
  __config _INTOSCIO & _WDT_OFF  ;   8 Mhz int-osc with IO:s
      

 ; define Data memory
inner equ 0x20
outer equ 0x21
 
 ; Bank shared memory (0x70-0x7f) used for Interrupt
 ; Interrupt backup registers
int_w          equ 0x70
int_status     equ 0x71
int_pclath     equ 0x72 ; not yet used at interrupts
int_indf    equ 0x73 ; not yet used at interrupts

 ; Debug serial port (Note.. buffer location not yet determined
ser_tx        equ 0x74  ; Zeroes reg after send
ser_rx        equ 0x75  ; 0 = no data
ser_status    equ 0x76  ; Todo! ; Define modes/error codes


 ; 24-bit ms tick counter (allocation for 32-bit int)
ms_32     equ 0x7c
ms_high equ 0x7d
ms_med  equ 0x7e
ms_low  equ 0x7f
               
  ; Start from reset vector
  
  org 0x00 ; obvious, but just in case.
  goto Main ; Skip over interrupt vector

  org 0x04 ; Interrupt vector
Intserver
  ; Save W, STATUS  (3 cycles)
  movwf int_w
  swapf STATUS,W ; only way to move status without affecting the Z-flag
  movwf int_status

  ; Real interrupt routine (remember to clear the interrupt)
  ; note: We have no idea about status flags (including RP0)
  ; Since this interrupt happens every 2000:th cpu clock, we'll just
  ; increment the ms-counters 
  movlw 0x01
  addwf ms_low, F
  btfsc STATUS, C ; if carry not happen skip increment
   addwf ms_med, F
  btfsc STATUS, C ; if carry not happen skip increment
   addwf ms_high, F
  bcf PIR1, TMR2IF ; Clear interrupt 


Intserver_end
  ; Restore W, STATUS and return from int (6 cycles)
  swapf int_status, W
  movwf    STATUS 
  swapf int_w, F
  swapf int_w, W  ; return W without messing with Status flags   
  retfie ; return with interrupts enabled.

  org 0x100  ; main program
Main
 ; Init IO ports
  BCF STATUS,RP0 ;Bank 0
  CLRF PORTC ;Init PORTC
  BSF STATUS,RP0 ;Bank 1
  CLRF ANSEL ;digital I/O  (disable Analog Inputs)
  MOVLW 0xFE ;Set RC<5:1> as input
  MOVWF TRISC ;and set RC<0> as outputs
  BCF STATUS,RP0 ;Bank 0

 ; Init Timer2 and real time clocks
  movlw 0x00
  movwf ms_high
  movwf ms_med
  movwf ms_low
 
 ; Sample of Timer2 settings for various interrupts at 8MHz xtal.
 ; Values in decimal.
 ; Clk    PR2    Pre    post    Usage
 ; 2000    125    16    1        1ms timer for real time system clock
 ;  208    208     1     1         9600 bps Tx async debug serial
 ;   69  69     1    1        9600 bps Rx async debug serial (3* subsample)
 ; Last one will tax system badly

 clrf TMR2
 bcf PIR1, TMR2IF ; Clear interrupt (should be anyhow)

 bsf STATUS, RP0 ; Bank1
 movlw 0x7d ; 125 decmal
 movwf PR2
 bsf PIE1, TMR2IE ; Allow timer2 interrupt.
 
 bcf STATUS, RP0 ; bank0
 movlw 0x06 ; Prescaler *16 + OscOn. 
 movwf T2CON ; Set t2 scalers + start the timer  
 bsf INTCON, PEIE ; Enable periferal int
 bsf INTCON, GIE ; Global interrupt enable
 

Loop
  movf  ms_med,W 
  movwf PORTC    ; Blink period of 512 ms

  goto  Loop             ;Do this repeatedly

  end                    ;All things must end someday

No comments:

Post a Comment