|
|
View previous topic :: View next topic |
Author |
Message |
hoteloskar
Joined: 01 Nov 2006 Posts: 3
|
Second interrupt caused wake-up |
Posted: Wed Nov 01, 2006 1:06 pm |
|
|
I'm using a 16LF876A where the internal USART is already used to feed an MP3 chip. But because of needing a further serial character input with interrupt capability I am using RB0 as a serial input.
Everything works fine, except when the sleep instruction is executed. Just every second (2.) incoming character will cause a wake-up. Also the ISR will not be executed at the first character, only at the second (2.) character.
Here is the code:
Code: |
#use rs232(baud=9600, xmit=PIN_A2,rcv=PIN_B0)
char flag;
#int_ext
void ext_isr () {
char c = 0;
c = getc();
putc(c)
if(c == 'A') flag = 1;
INTF = 0;
}
void main() {
ext_int_edge(H_TO_L);
enable_interrupts(int_ext);
enable_interrupts(global);
while (1 == 1) {
sleep();
#asm
NOP
#endasm
if (flag) {
flag = 0;
puts("wake-up");
}
}
}
|
Best Regards
Hans |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 01, 2006 4:23 pm |
|
|
Quote: | Everything works fine, except when the sleep instruction is executed.
Just every second (2.) incomming character will cause a wake-up.
Also the ISR will not be executed at the first character, only at the
second (2.) character. |
Read Ttelmah's post at the end of this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=25990&highlight=sleep+wake+intext
I think there may be other threads on this topic, but I don't have time
to search for them now. |
|
|
hoteloskar
Joined: 01 Nov 2006 Posts: 3
|
|
Posted: Thu Nov 02, 2006 8:05 am |
|
|
Thanks for your very fast answer.
The link you provided makes it a bit clearer, but not completely.
When receiving the first character the PIC must change the state internaly
in any way. Because the second character will be sent 10 or more seconds later and is received (printed) immediately.
I also reduced the baud rate from 9600 to 300. This caused also a character printed immediately. But only garbage, because some bits from the character are lost.
The behaviour of the PIC for me looks like a human wake-up. At a first noise in the morning you will get from deep sleep into a light sleep and at the second noise you will wake-up completely.
Reagards, Hans |
|
|
Ttelmah Guest
|
|
Posted: Thu Nov 02, 2006 8:18 am |
|
|
The chip should be 'starting to wake' straight away, but won't be able to actually clock data in, until the master oscillator is up to speed. So the first character, is always going to either be garbage, or be missed completely. The chip will have woken up, but the data will be scrap, unless you run the chip from an external clock.
In your 'human' analogy, it is as if somebody starts talking into your ear, and wakes you. Though the noise wakes you up, you would not be able to say 'what they said'.
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Thu Nov 02, 2006 10:02 am |
|
|
As an 'ongoing comment', to explain what you are seeing, On the first falling edge of the first character, the chip starts to wake up. There is a pause, while the oscillator starts, and then the code jumps immediately to the ISR. The first thing you do in the ISR, is call 'getc'. Now on the software serial, this checks to see if the input line is 'low', and only if it is, does it start to receive the character. Otherwise it waits. Because of the time that has passed, the character has been missed, so the code sits waiting in the ISR. Only when the second character arrives, is the 'low' seen, and this is then received.
When you switched to using a much slower rate, the whole character had not been missed, but the start bit (or most of it), had been missed. Hence the reception starts at the next 'low' in the character, resulting in garbage.
If you code the ISR like this, you will see what is happening:
Code: |
char flag;
char data;
#int_ext
void ext_isr () {
char c = 0;
if (kbhit()) {
//only fetch a character if the line is low
c = getc();
putc(c)
if(c == 'A') data = 1;
}
flag=1;
//INTF = 0; - not needed the compiler does this for you
}
void main() {
ext_int_edge(H_TO_L);
enable_interrupts(int_ext);
enable_interrupts(global);
while (TRUE) {
sleep();
delay_cycles(1); //This provides the NOP
if (flag) {
flag = 0;
putc("Interrupt seen\n");
if (data) {
data=0;
putc("'A' seen\n");
}
}
}
}
|
Best Wishes |
|
|
hoteloskar
Joined: 01 Nov 2006 Posts: 3
|
|
Posted: Fri Nov 03, 2006 11:41 am |
|
|
Oh yes, thats it is.
Thank you very much for your great explanation. The hang-up in 'getc'
is the main problem.
I still was thinking over your previous reply, because it did not cover the whole problem. But now you hit it exactly.
I still was wondering why second character apears immediatly and correct.
Now I know it.
Thank you very much once again, you are a real professional
Best Regards
Hans |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|