View previous topic :: View next topic |
Author |
Message |
cyclo.sl
Joined: 07 Oct 2009 Posts: 11
|
PIC getting stuck |
Posted: Wed Oct 07, 2009 1:17 am |
|
|
Hi everyone
I'm writing a program for PIC18F4431.
I'm using printf and getch functions to communicate with a PC via RS232. Baudrate and other settings are correctly configured. The problem is when I send few bytes of data from the PC in a row, the pic is getting stuck. I always have to restart it.
My code is something similar to this.
Code: |
func x{
int8 x,y;
x= getch();
y= getch();
printf("two bytes received");
}
|
Why is it getting stuck? Thanks in advance. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Oct 07, 2009 10:19 am |
|
|
#use RS232 should include the "ERRORS" parm.
Read up on it... it clears overflows in the UART... which can cause things to stick like you describe (if I remember right).
On another note, in your code, you should have a check to see if there is even any data in the buffer... either
Code: | while (! kbhit() ); |
or
Code: | if ( kbhit() ) {
do some stuff;
}
|
Both had their obvious uses... choose which best suits your app.
For code that needs to run while waiting for data, I like to use ISR's and better defined packets...
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
cyclo.sl
Joined: 07 Oct 2009 Posts: 11
|
|
Posted: Wed Oct 07, 2009 11:41 am |
|
|
Thanks Ben..
I'll check and add that parm.
I used if (kbhit()) but it gave the same result. Ya I guess I have to use interrupts here. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Oct 07, 2009 12:37 pm |
|
|
I spaced,
In your case,
You would want:
Code: | func x{
int8 x,y;
if ( kbhit() ) {
x= getch();
}
if ( kbhit() ) {
y= getch();
}
printf("two bytes received");
} |
I will say an ISR with something that frames the data coming through is very nice albeit busier.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
cyclo.sl
Joined: 07 Oct 2009 Posts: 11
|
|
Posted: Wed Oct 07, 2009 10:55 pm |
|
|
Thanks again Ben..
Well the thing is, in my case I want my code to stay in the blocked state till I receive 2bytes of data. Means the calculation needs two byte of data to proceed, so I have to wait till the user input 2 values from the sw in pc. But if I use kbhit(), my code wont stay in the blocked state. Then I will have to use a blocking loop with kbhit(). So using getch() alone is good for my case, isn't it? |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Oct 07, 2009 11:19 pm |
|
|
Well you can't "wait until 16 bits" because the UART and RS232 in general works on 8bits at a time.
So the initial receive signals a byte... your (or my) code goes and grabs it..
We have 1.
What now?
If we do another getch(), what are we getting? another byte? How? The CPU is running at MIPS while the UART is transferring at some fraction of that speed even at 115,200b/s...
so that second "ungated" getch() is grabbing invalid dat we don't want anyway. We have to wait for the UART to signal it has another byte that we can get before continuing. Thus, the second if (kbhit()).
To sum it up, getch() takes a received char out of the RX buffer. You can't getch() something that doesn't exist yet and the only way you can know it's there is to check the reciever status yourself through kbhit() or by checking the receiver status bit which on most PICs is the RCxIF interrupt flag. (the bit always works, but does/doesn't generate an interrupt based on the enable bit and the global interrupt bit).
Let me know if that helps,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
cyclo.sl
Joined: 07 Oct 2009 Posts: 11
|
|
Posted: Thu Oct 08, 2009 1:33 am |
|
|
You are exactly addressing my problem.
This is a part of the exact code I used.
Code: |
struct bytes{
int8 low;
int8 high;
};
union duty_val{
int16 value;
struct bytes parts;
};
void main(){
union duty_val duty1,duty2,duty3,duty4;
while(true){
printf("waiting for duty values..");
duty1.parts.high = getch();
duty1.parts.low = getch();
printf("duty1 : %Lu ",duty1.value);
duty2.parts.high = getch();
duty2.parts.low = getch();
printf("duty2 : %Lu ",duty2.value);
duty3.parts.high = getch();
duty3.parts.low = getch();
printf("duty3 : %Lu ",duty3.value);
duty4.parts.high = getch();
duty4.parts.low = getch();
printf("duty4 : %Lu ",duty4.value);
//calculations
}
} |
I wrote a C# application to send above duty values. Initially I coded it to transfer 8 bytes of data when I press a button. That did not work as the pic started to get stuck after I receive "duty1:xx". (You already gave me an answer for that problem) So what I did was, I inserted a delay in between 2 bytes wondering why this happens even the both ends work at the same baud rate. Got the problem solved with that. Yet when I keep pressing the button, the same problem happens.
These are the modifications that I'm going to make.
1. Add ERRORS param to #use rs232
2. Modify the code as below
Code: |
printf("waiting for duty values..");
while(!kbhit());
duty1.parts.high = getch();
while(!kbhit());
duty1.parts.low = getch();
printf("duty1 : %Lu ",duty1.value);
|
Hope I've understood you correctly. Will keep you updated.
Thanks |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Oct 08, 2009 12:12 pm |
|
|
Yep -- I think you're on the right track now.
Holler if you need it. :D
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|