Electronics > Microcontrollers
Need help with PIC16F88, assembly and Timer0 interrupts
elliot42:
I've been mucking about with PICs lately, with the intention to make a VCO using wavetable synthesis on the PIC.
I've never used PICs or assembly before and I'm having trouble getting the Timer0 interrupt to work how I expect it to work.
In the code below I'm setting the prescaler to be assigned to Timer0 and to have a ratio of 1:128, so I expected to get an interrupt event every 16.384ms (I think **), but the interrupt just seems to be running as fast as it possibly can.
I've taken images from my DSO showing on channel 1 the CLKOUT (Fosc / 4 = 8Mhz / 4 = 2Mhz), and on channel 2 the output of PORTA,1 that I'm setting high and low in the interrupt routine.
Interestingly, when I add 2 nop instructions between the bsf/bcf in the interrupt routine, the frequency at which the interrupt occurs decreases.
Also, when the Timer0 interrupt is enabled (bsf INTCON,TMR0IE) I get no output on PORTA,0 which I set in the loop; when I disable the interrupt I get output there.
** 8Mhz (clock) / 4 (4 clocks per instruction cycle) = 2Mhz
1 / 2Mhz (freq -> time) * 256 (8-bit Timer0 counter) * 128 (prescaler ratio) = 16,384us
Can anyone explain this to me? Am I doing something wrong or do I not understand how this is meant to work?
--- Code: --- LIST P=16F88
#INCLUDE "p16F88.inc"
__CONFIG _CONFIG1, _CPD_OFF & _CP_OFF & _DEBUG_OFF & _LVP_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _WRT_PROTECT_OFF & _INTRC_CLKOUT & _BODEN_OFF
org 0x00
goto main
org 0x04
bsf PORTA,1
bcf PORTA,1
retfie
main:
clrf STATUS
clrf PORTA
clrf PORTB
movlw 0x00
banksel TRISA
movwf TRISA
banksel TRISB
movwf TRISB
banksel ANSEL
clrf ANSEL
banksel OSCCON
bsf OSCCON,IRCF2
bsf OSCCON,IRCF1
bsf OSCCON,IRCF0
bcf OSCCON,SCS0
bcf OSCCON,SCS1
banksel PORTA
clrf PORTA
clrf PORTB
banksel OPTION_REG
bcf OPTION_REG,T0CS
bcf OPTION_REG,PSA
bsf OPTION_REG,PS2
bsf OPTION_REG,PS1
bcf OPTION_REG,PS0
banksel INTCON
bsf INTCON,TMR0IE ; enable TMR0 interrupt
bsf INTCON,GIE ; enable interrupt globally.
loop:
bsf PORTA,0
nop
nop
bcf PORTA,0
goto loop
--- End code ---
David_AVD:
--- Quote from: elliot42 on July 12, 2012, 11:55:38 pm ---In the code below I'm setting the prescaler to be assigned to Timer0 and to have a ratio of 1:128, so I expected to get an interrupt event every 16.384ms (I think **), but the interrupt just seems to be running as fast as it possibly can.
--- End quote ---
One obvious issue is that you're not clearing the interrupt flag when you service it.
Also, the bsf / bcf method of twiddling the port bits on a PIC16F88 will result in RMW issues. (lots of info on that if you search)
notsob:
PIC RMW - ReadModifyWrite issues
http://www.piclist.com/techref/readmodwrite.htm
notsob:
If you are beginning ASM on PIC there are some tutorials on pcbheaven.com
elliot42:
Thank you, David, notsob. I have been looking at the Timer0 tutorial on PCBHeaven and must have just read past this bit:
--- Quote from: pcbheaven.com ---The TMR0IF must be cleared in software (BCF INTCON,TMR0IF) for the TMR0 interrupt to be re-enabled.
--- End quote ---
Thanks for pointing it out.
Thanks for the info too about the RMW issues.
I am just starting out with ASM, been at it for only a week. I've done some stuff with Arduinos before in C and I program in Java and C++ (and sometimes Python, Ruby, sh, SQL) at work, but thought I'd try learning about the lower-level operations of the PIC instead of just using C and copying some tutorials.
Navigation
[0] Message Index
[#] Next page
Go to full version