***************************************************************************** ***************************************************************************** ** ** ** File.................: timer_isr.asm ** ** Function.............: This file drives a Motorola 68HC908GP32 ** ** microcontroller. It sets up an interrupt service routine that ** ** will fire every 1 second. Every time the ISR is executed, a ** ** variable called state is inverted. The main loop examines this** ** variable and either turns on or off the port c pins. If LEDs ** ** are connected in series with 200 ohm resisters, the LEDS will ** ** flash on and off with a frequency of 2 Hz. ** Note: The CNT_HI and CNT_LO constants define the time that the ** ** timers will run to before setting an overflow interrupt on ** ** timer1. Further note the settings for T1SC where a prescaler ** ** of 64 is set. This prescaler divides the cpu clock by 64 so ** ** every increment of the timer 1 counter (read at TCNTH/L) is 64 ** ** cpu clock cycles. ** Recall that the cpu clock is the external clock freq / 4 ** ** Thus, for an external clock freq of 9.8304 MHz ** cpu_clk = 9.8304 MHz / 4 = 2.4576 MHz which is a period of** ** 407 ns / clk cycle period) ** With a prescaler of 64 then 2.4576 MHz/64 = 38.4 KHz which ** ** is a period of 26 us (microseconds). So with these settings ** ** every count of T1CNTH/L is 26 us. ** If I want the Interrupt Service Routine to fire every 1 seconds** ** then I calculate the number of counts required. ** 1 sec / 26 us = 38461 = 0x963D. So I set the modulus registers** ** of timer1 for 0x963D. ** If you want a different frequency, just figure out how long you ** ** have the timer run before triggering an interrupt, divide this ** ** the cpu_clk / 4 / prescaler to get a count value, convert it to** ** hex and put that into the constant CNT_HI/LO. ** But, remember that you do not want to set the counter values to ** ** a time period that is less than the amount of time to execute ** ** all of the instructions in the ISR. ************************************************************************************************* ************************************************************************************************* * Equates * * * * These are the locations of various MCU registers for the 68HC908GPXX MCU. * ************************************************************************************************* pta equ $00 ;port a data register ptb equ $01 ;port b data register ptc equ $02 ;port c data register ptd equ $03 ;port d data register pte equ $08 ;port e data register ddra equ $04 ;port a data direction register ddrb equ $05 ;port b data direction register ddrc equ $06 ;port c data direction register ddrd equ $07 ;port d data direction register ddre equ $0C ;port e data direction register scc1 equ $13 ;sci control register 1 scc2 equ $14 ;sci control register 2 scc3 equ $15 ;sci control reg 3 scs1 equ $16 ;sci status reg 1 scs2 equ $17 ;sci status reg 2 scdr equ $18 ;sci data reg scbr equ $19 ;sci baud rate reg config2 equ $1E ;sci config reg 2 config1 equ $1f ;config register 1 t1sc equ $20 ;timer 1 status and control reg t1cnth equ $21 ;timer 1 counter reg high t1cntl equ $22 ;timer 1 counter reg low t1modh equ $23 ;timer 1 modulo reg high t1modl equ $24 ;timer 1 modulo reg low t1sc0 equ $25 ;timer 1 channel 0 status and control reg t1ch0h equ $26 ;timer 1 channel 0 reg high t1ch0l equ $27 ;timer 1 channel 0 reg low t2sc equ $20 ;timer 1 status and control reg t2cnth equ $21 ;timer 1 counter reg high t2cntl equ $22 ;timer 1 counter reg low t2modh equ $23 ;timer 1 modulo reg high t2modl equ $24 ;timer 1 modulo reg low t2sc0 equ $25 ;timer 1 channel 0 status and control reg t2ch0h equ $26 ;timer 1 channel 0 reg high t2ch0l equ $27 ;timer 1 channel 0 reg low ram equ $40 ;start of ram flash equ $8000 ;start of flash ($b000 for GP20, $8000 for GP32) *******************Specific to this application equates************************ CNT_HI equ $96 ;counter values for 1 sec with 9.8304 MHz CNT_LO equ $3D ;clock and a 64 prescaler divider ************************************************************************************************* * Interrupt Vectors * * * * Go to interrupt vector area and fill with init to prevent any interrupts from affecting the * * code. * ************************************************************************************************* org $ffdc ;fill interrupt vectors fdb init ;timebase vector address fdb init ;conversion complete vector address fdb init ;keyboard pin vector address fdb init ;sci transmit complete, empty vector address fdb init ;sci idle or receiver full vector address fdb init ;sci parity, framing, noise, overrun error address fdb init ;spi transmitter empty vector address fdb init ;spi full,over,fault vector address fdb init ;tim2 overflow vector address fdb init ;tim2 channel 1 vector address fdb init ;tim2 channel 0 vector address fdb timer1_isr ;tim1 overflow vector address fdb init ;tim1 channel 1 vector address fdb init ;tim1 channel 0 vector address fdb init ;cgm (pll) vector address fdb init ;IRQ pin vector address fdb init ;swi instruction vector address fdb init ;reset vector address org ram state rmb 1 ;variable to hold whether output is low or hi ************************************************************************************************* * Initialization * * * * This section clears variables, and sets up internal registers for the microcontroller * ************************************************************************************************* org flash ;start main code at the beginning of flash init mov #$01,config2 ;Osc disable on stop, SCI clock source internal mov #$01,config1 ;COP disabled, all other default (see p142) ldhx #$0240 ;load HX with the end of memory location txs ;put the stack pointer at the end of memory clra ;clears A, X, and H regs clrx clrh **************** memory definitions ***************************** clr ptc mov #$ff,ddrc ; set up port c as output clr state ****************** Init Timer 1 ************************************* mov #$76,t1sc ;stop/reset cntr/interrupt enabled,prescaler 64 mov #CNT_HI,t1modh mov #CNT_LO,t1modl mov #$46,t1sc ;start timer, intrpt enabled, prescaler 64 ************************************************************************************************* * Main Program * * This is the main section of the code. * ************************************************************************************************* cli ;turn on interrupts loop: bra loop ;loop forever. The ISR does all the work here timer1_isr: com state ; complement state lda state ;load accumulator with variable state's contents beq off_leds ;if it is zero, branch to the off_leds routine bra on_leds ;otherwise branch to turn on all portc pins off_leds: mov #$00,ptc ;turn off all portc pins bra clear_interrupt ;branch to routine to clear and return from interrupt on_leds: mov #$FF,ptc ;turn on portc pins clear_interrupt: ; now we need to clear the interrupt lda t1sc ;read t1sc bclr 7,t1sc ;write a 0 to the TOF flag bit in T1SC rti ;and return from interrupt