EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Strange behaviour in PIC18 interrupt

Started by R. Wilcock January 13, 2005
I am using a PIC18F4320 and have been trying to solve a very strange
problem..

I have configured an interrupt using Timer1 which fires every 1ms. In
that interrupt an ascii character gets sent, and is incremented, every
time. Also, every 79 interrupts another section of the code gets
executed, which just sends a '%' and resets the ascii code to '1'.

Nothing else is going on AT ALL in the program (i.e. no main routines
at all). There are NO other interrupts running, just this one. The PIC
is running at 40MHz and the serial comms are at 115,200 baud. Looking
at the output on hyperterminal, it works fine streaming these lines of
79 ascending ascii characters and then a '%' then periodically, about
every 13 lines of this some characters get missed. Its really odd.

Changing the baud rate makes no change at all to the problem. Changing
the interrupt rate even just the tiniest bit either makes the problem
never occur or occur much much less often. Changing the clock rate
also makes the problem disappear (from 40MHz to 10MHz). I literally
have been stripping the program down to find the problem and its just
one interrupt routine now, sending this data - note I even got rid of
the context saving at the start and end to see if that helped...:

int
	btfsc	PIR1,0		; check if its the timer
	goto	int_timer1	; in which case service the interrupt
	goto	int_end		; else go to the end
int_timer1		        ; comes here every 1.0002ms
	incf	SPECIAL
	movf	SPECIAL,W
	addlw	0x30		; so we are in numbers
	movwf	TXREG
	movlw	Timer1L		; setup the timer period again
	movwf	TMR1L		;
	movlw	Timer1H		;
	movwf	TMR1H		;
	bcf	PIR1,0	        ; clear the flag
	decfsz	INTDIV1		; divide the interrupt by 10
	goto	int_end
int_timer2
	clrf	SPECIAL
	movlw	'%'
	movwf	TXREG
	movlw	IntDiv				
	movwf	INTDIV1		;
int_end				;
	retfie			; return from int

Any suggestions? I couldn't paste the output from hyperterminal in
here because the wrapping messed it up - go here for a screen shot:

http://www.ecs.soton.ac.uk/~rw3/problems.jpg

you can see the weird glitch happening three times in that window.

Hope someone can help! I could of course just change the interrupt
rate which solves it, but I would like to know the cause of the
problem,

Cheers,

Reuben
R. Wilcock wrote:
> I am using a PIC18F4320 and have been trying to solve a very strange > problem.. > > I have configured an interrupt using Timer1 which fires every 1ms. In > that interrupt an ascii character gets sent, and is incremented,
every
> you can see the weird glitch happening three times in that window. > > Hope someone can help! I could of course just change the interrupt > rate which solves it, but I would like to know the cause of the > problem, >
Are you SURE this isn't a problem with hyperterminal/your PC serial port? There are many problems with hyperterminal and the screenshot you have looks just like hyperterminal is throwing characters away.. Iain
"R. Wilcock" wrote:

> Looking > at the output on hyperterminal, it works fine streaming these lines of > 79 ascending ascii characters and then a '%' then periodically, about > every 13 lines of this some characters get missed. Its really odd.
> int > btfsc PIR1,0 ; check if its the timer > goto int_timer1 ; in which case service the interrupt > goto int_end ; else go to the end > int_timer1 ; comes here every 1.0002ms > incf SPECIAL > movf SPECIAL,W > addlw 0x30 ; so we are in numbers > movwf TXREG > movlw Timer1L ; setup the timer period again > movwf TMR1L ; > movlw Timer1H ; > movwf TMR1H ; > bcf PIR1,0 ; clear the flag > decfsz INTDIV1 ; divide the interrupt by 10 > goto int_end > int_timer2 > clrf SPECIAL > movlw '%' > movwf TXREG > movlw IntDiv > movwf INTDIV1 ; > int_end ; > retfie ; return from int > > Any suggestions?
I have two thoughts: 1. If updating the timer register while it is running, you may have a problem if the timer is in the process of rolling the ls byte over and carrying to the ms byte. For that, you can disable the timer while updating. 2. Program another controller to look at the input characters and set a output whenever a wrong character is seen. Use this to trigger a digital scope looking at the serial line to get a better idea of what is happening: is there unusual timing between characters, etc. Thad
"R. Wilcock" wrote:
> > I am using a PIC18F4320 and have been trying to solve a very strange > problem.. > > I have configured an interrupt using Timer1 which fires every 1ms. In > that interrupt an ascii character gets sent, and is incremented, every > time. Also, every 79 interrupts another section of the code gets > executed, which just sends a '%' and resets the ascii code to '1'. > > Nothing else is going on AT ALL in the program (i.e. no main routines > at all). There are NO other interrupts running, just this one. The PIC > is running at 40MHz and the serial comms are at 115,200 baud. Looking > at the output on hyperterminal, it works fine streaming these lines of > 79 ascending ascii characters and then a '%' then periodically, about > every 13 lines of this some characters get missed. Its really odd. > > Changing the baud rate makes no change at all to the problem. Changing > the interrupt rate even just the tiniest bit either makes the problem > never occur or occur much much less often. Changing the clock rate > also makes the problem disappear (from 40MHz to 10MHz). I literally > have been stripping the program down to find the problem and its just > one interrupt routine now, sending this data - note I even got rid of > the context saving at the start and end to see if that helped...:
I suspect your difficulty really has to do with hyperterminal/Windoze and unterminated lines rather than the sender. Try terminating the lines with <cr> or '\n' rather than '%', or with both. Try another terminal program, such as Telix or ProComm. Receive it on a machine running plain MSDOS rather than Windoze. Is the PC RS232 interface using something like a USB intermediary, or do you have a real RS232 port? -- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers." - Keith Thompson
>I am using a PIC18F4320 and have been trying to solve a very strange >problem.. > >I have configured an interrupt using Timer1 which fires every 1ms. In >that interrupt an ascii character gets sent, and is incremented, every >time. Also, every 79 interrupts another section of the code gets >executed, which just sends a '%' and resets the ascii code to '1'. > >Nothing else is going on AT ALL in the program (i.e. no main routines >at all). There are NO other interrupts running, just this one. The PIC >is running at 40MHz and the serial comms are at 115,200 baud. Looking >at the output on hyperterminal, it works fine streaming these lines of >79 ascending ascii characters and then a '%' then periodically, about >every 13 lines of this some characters get missed. Its really odd. > >Changing the baud rate makes no change at all to the problem. Changing >the interrupt rate even just the tiniest bit either makes the problem >never occur or occur much much less often. Changing the clock rate >also makes the problem disappear (from 40MHz to 10MHz). I literally >have been stripping the program down to find the problem and its just >one interrupt routine now, sending this data - note I even got rid of >the context saving at the start and end to see if that helped...: > >int > btfsc PIR1,0 ; check if its the timer > goto int_timer1 ; in which case service the interrupt > goto int_end ; else go to the end >int_timer1 ; comes here every 1.0002ms > incf SPECIAL > movf SPECIAL,W > addlw 0x30 ; so we are in numbers > movwf TXREG > movlw Timer1L ; setup the timer period again > movwf TMR1L ; > movlw Timer1H ; > movwf TMR1H ; > bcf PIR1,0 ; clear the flag > decfsz INTDIV1 ; divide the interrupt by 10 > goto int_end >int_timer2 > clrf SPECIAL > movlw '%' > movwf TXREG > movlw IntDiv > movwf INTDIV1 ; >int_end ; > retfie ; return from int > >Any suggestions? I couldn't paste the output from hyperterminal in >here because the wrapping messed it up - go here for a screen shot: > >http://www.ecs.soton.ac.uk/~rw3/problems.jpg > >you can see the weird glitch happening three times in that window. > >Hope someone can help! I could of course just change the interrupt >rate which solves it, but I would like to know the cause of the >problem, > >Cheers, > >Reuben > >
Sounds like you are sending too quickly for hyperterminal. Try putting some pauses into the stream, say every 16 bytes, or maybe implement XON/XOFF or hardware handshaking.
Thanks for all the responses:

Iain: this is something I am trying to determine right now. I believe that 
it is not the computer, because I have tried different baud rates and 
exactly the same thing happens (even with very slow baud rates). I have 
tried 3 different serial monitors and all three show the same thing.

Thad: The timer registers are such that you update the high one then the low 
one and only when you have updated the low one, both are written (i.e. the 
regs you write to are not the actual timer regs). The idea of having another 
PIC to check the output is a good idea - I had planned to do this today.

CBFalconer: The problem was originally spotted when the normal program 
functionality was running, which contained plenty of end of regular 
terminated lines, so this is not the problem. I have tried it with 3 
terminal programs and all show the same response. This is direct to serial, 
not with USB VCP.

Ppelectron: I doubt that I am sending it too often - once every ms is 
nothing for a baud rate of 115,200. In any case, the original program had 
plenty of spaces and end of line characters etc.. and the problem was still 
there (this example I have put is just to try and nail down to the problem).

Any more suggestions?

Cheers,

Reuben


On 13 Jan 2005 06:52:56 -0800, reubenwilcock@hotmail.com (R. Wilcock)
wrote:
>I am using a PIC18F4320 and have been trying to solve a very strange >problem.. > >I have configured an interrupt using Timer1 which fires every 1ms. In >that interrupt an ascii character gets sent, and is incremented, every >time. Also, every 79 interrupts another section of the code gets >executed, which just sends a '%' and resets the ascii code to '1'. > >Nothing else is going on AT ALL in the program (i.e. no main routines >at all). There are NO other interrupts running, just this one. The PIC >is running at 40MHz and the serial comms are at 115,200 baud. Looking >at the output on hyperterminal, it works fine streaming these lines of >79 ascending ascii characters and then a '%' then periodically, about >every 13 lines of this some characters get missed. Its really odd. > >Changing the baud rate makes no change at all to the problem. Changing >the interrupt rate even just the tiniest bit either makes the problem >never occur or occur much much less often. Changing the clock rate >also makes the problem disappear (from 40MHz to 10MHz). I literally >have been stripping the program down to find the problem and its just >one interrupt routine now, sending this data - note I even got rid of >the context saving at the start and end to see if that helped...: > >int > btfsc PIR1,0 ; check if its the timer > goto int_timer1 ; in which case service the interrupt > goto int_end ; else go to the end >int_timer1 ; comes here every 1.0002ms > incf SPECIAL > movf SPECIAL,W > addlw 0x30 ; so we are in numbers > movwf TXREG > movlw Timer1L ; setup the timer period again > movwf TMR1L ; > movlw Timer1H ; > movwf TMR1H ; > bcf PIR1,0 ; clear the flag > decfsz INTDIV1 ; divide the interrupt by 10 > goto int_end >int_timer2 > clrf SPECIAL > movlw '%' > movwf TXREG > movlw IntDiv > movwf INTDIV1 ; >int_end ; > retfie ; return from int > >Any suggestions? I couldn't paste the output from hyperterminal in >here because the wrapping messed it up - go here for a screen shot: > >http://www.ecs.soton.ac.uk/~rw3/problems.jpg > >you can see the weird glitch happening three times in that window. > >Hope someone can help! I could of course just change the interrupt >rate which solves it, but I would like to know the cause of the >problem, Cheers, Reuben
Reuben, Can you post the entire program with initialization? Any chance the watchdog time has been enabled? How is int_timer2 accessed? Do you have Timer1 configured for 8bit or 16bits writes? "A write to the high byte of Timer1 must also take place through the TMR1H Buffer register. Timer1 high byte is updated with the contents of TMR1H when a write occurs to TMR1L. This allows a user to write all 16 bits to both the high and low bytes of Timer1 at once. The high byte of Timer1 is not directly readable or writable in this mode. All reads and writes must take place through the Timer1 High Byte Buffer register. Writes to TMR1H do not clear the Timer1 prescaler. The prescaler is only cleared on writes to TMR1L."
On 13 Jan 2005 06:52:56 -0800, the renowned reubenwilcock@hotmail.com
(R. Wilcock) wrote:

>I am using a PIC18F4320 and have been trying to solve a very strange >problem.. > >I have configured an interrupt using Timer1 which fires every 1ms. In >that interrupt an ascii character gets sent, and is incremented, every >time. Also, every 79 interrupts another section of the code gets >executed, which just sends a '%' and resets the ascii code to '1'. > >Nothing else is going on AT ALL in the program (i.e. no main routines >at all). There are NO other interrupts running, just this one. The PIC >is running at 40MHz and the serial comms are at 115,200 baud. Looking >at the output on hyperterminal, it works fine streaming these lines of >79 ascending ascii characters and then a '%' then periodically, about >every 13 lines of this some characters get missed. Its really odd. > >Changing the baud rate makes no change at all to the problem. Changing >the interrupt rate even just the tiniest bit either makes the problem >never occur or occur much much less often. Changing the clock rate >also makes the problem disappear (from 40MHz to 10MHz).
This is a clue. Have you checked the errata for the chip? More specifically, have you checked the errata for the chip you are using, not for the latest silicon revision (or, alternately, tried the silicon revision that is current). There were a number of "issues" with early 18F parts running at full speed. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
R. Wilcock wrote:

> I am using a PIC18F4320 and have been trying to solve a very strange > problem.. > > I have configured an interrupt using Timer1 which fires every 1ms. In > that interrupt an ascii character gets sent, and is incremented, every > time. Also, every 79 interrupts another section of the code gets > executed, which just sends a '%' and resets the ascii code to '1'.
So you have two code blocks that want to use the UART, one of which is a timerINT - or the UART is ONLY under the 1msINT control, which 78/79 does CH_TX, and 1/79 does %_TX ?
> > Nothing else is going on AT ALL in the program (i.e. no main routines > at all). There are NO other interrupts running, just this one. The PIC > is running at 40MHz and the serial comms are at 115,200 baud. Looking > at the output on hyperterminal, it works fine streaming these lines of > 79 ascending ascii characters and then a '%' then periodically, about > every 13 lines of this some characters get missed. Its really odd. > > Changing the baud rate makes no change at all to the problem. Changing > the interrupt rate even just the tiniest bit either makes the problem > never occur or occur much much less often. Changing the clock rate > also makes the problem disappear (from 40MHz to 10MHz).
There are clues there. Sounds like a classic aperture effect - hard part is to figure out where/what the critical aperture is :) You could very slowly sweep the timer rate, and try and track the failure pattern. What about other clocks, between 10Mhz and 40MHz ? -jg
Interesting one... I don't know PIC in depth, but here are some 
obervations...

* I see you are using 8-N-1 in the screenshot, so this isn't a clock 
slip / parity failure, or you'd see garbage.  It'd seem the USART is not 
sending at all.

* The values keep incrementing, so clearly the ISR keeps firing.  Again, 
you need to focus on why the USART isn't sending.

* I only see 2 skips in the screen shot - one is ~63 characters, the 
other is ~73. They're ~882 characters apart.  Look for more patterns 
like this and see if you can find trends that hint at a cause.  (Like, 
is the number of milliseconds or characters consistant at different baud 
rates?)

* Does the USART support any hardware flow controls?  Are their inputs 
floating?

* Have you tried checking (halting on) USART status flags before / after 
loading the USART buffer?  Maybe it's reporting a condition that you're 
ignoring.  At 1mS & 115Kb, it shouldn't ever fill up, but this might 
narrow your search.

* What's your USART accuracy at 115Kb with 10MHz vs. 40MHz?  I'd suggest 
you're cutting your timing budget too close, but if it happens at lower 
baud rates too, this isn't likely the issue.  Have you checked your 
bit/byte timing with a scope to confirm the accuracy?

Cheers,
Richard

The 2024 Embedded Online Conference