View previous topic :: View next topic |
Author |
Message |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
Questions About Standard Serial ISR |
Posted: Tue Oct 25, 2005 4:34 pm |
|
|
Hello All,
I've been trying to solve a problem with a set of serial radios. I got deep into the serial ISR and figured I'd be alot better off if I understood what was happening. (Luckily, I think the problem is hardware, but I still have questions...)
Here's the code:
Code: | /*******************************
Serial ISR Support
*******************************/
#define BUFFER_SIZE 32
byte buffer[BUFFER_SIZE];
byte next_in = 0;
byte next_out = 0;
#define bkbhit (next_in!=next_out)
char cmd_str[20];
/*******************************
Serial Receive Buffer ISR
*******************************/
#int_rda
void serial_isr()
{
int t;
buffer[next_in]=getc();
t = next_in;
next_in = (next_in+1) % BUFFER_SIZE;
if(next_in == next_out)
next_in = t; // Buffer full !!
}
byte bgetc()
{
byte c;
while(!bkbhit) ;
c = buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void get_cmd_str(char * s, int max) {
int len;
char c;
max--;
len = 0;
do {
c = bgetc();
if(c > 0x00) {
if(len < max) {
s[len++] = c;
}
}
}
while(bkbhit);
s[len]= 0x00;
}
main() {
/******* Serial Buffer Retrieve ***********/
if(bkbhit) {
delay_ms(50); //Delay allows full string to arrive
get_cmd_str(cmd_str, 10);
}
/******* End Serial Buffer Retrieve ***********/
} |
My general understanding of what's happening:
1. Character arrives in PIC UART
2. int_rda is triggered (every time a character arrives, no?)
3. serial_isr() is executed and arriving character is put in buffer[next_in]
Steps 1 - 3 happen with each character arrival.
4. If there is a disagreement between the number of characters received and the number fetched (bkbhit) then get_cmd_str() is executed.
Questions:
What is the purpose of:
in bgetc()?
What is the meaning of "bkbhit" is it a mnemonic for something?
Thanks,
John |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Tue Oct 25, 2005 4:56 pm |
|
|
It is really while(!bkbhit);
While not bkbhit, wait forever.
OR
while (not(next_in!=next_out) wait forever
OR
while(next_in==next_out) wait forever
OR
if nothing in the buffer ie: indexes are the same, wait forever
Quote: |
byte bgetc()
{
byte c;
while(!bkbhit) ;
c = buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
|
So if you call bgetc and the indexes are the same you will sit there and WAIT untill the RX-ISR breaks you out saves a byte in the buffer, increments an index and next_in!=next_out |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Tue Oct 25, 2005 5:08 pm |
|
|
OK, now I get the picture. I didn't put 2 and 2 together with that statement. I just assumed it wasn't doing anything. But really, bkbhit gets updated in each interrupt.
Thanks,
John |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
Adding to this... |
Posted: Wed Oct 26, 2005 6:44 am |
|
|
Just thought I'd elaborate a bit.
The kbhit() function is from desktop computer/terminal architecture. It detects when a key on the keyboard has been hit (kbhit) by checking for data in the keyboard buffer. I don't think this applies to serial comms on a PC for example, but CCS have used it as such for their compiler.
The 'bkbhit' function (b for buffer?) is just a re-written one to check your 'home-made' buffer. You can't name it 'kbhit' as this is already a built in function.
Also, with the serial ISR, and bgetc() as the buffer is a binary value (32), you can save on machine cycles (unless the compiler already optimises this for you?) by using the AND operator.
Code: | next_in = (next_in+1) & (BUFFER_SIZE-1); |
Note the use of "buffer size -1" You want the pointer to wrap around from 31, back to 0, not 32 You don't need this with the % operator, as 32%32=0 which gives the same result as 32&31=0 but I think using the & operator will be more code efficient. You can define "buff_limit" as "buff_size-1" and also save on a subtraction.
eg.
0 & 31 = 0
1 & 31 = 1
...
31 & 31 = 31
32 & 31 = 0 |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Oct 26, 2005 8:20 am |
|
|
Quote: |
I've been trying to solve a problem with a set of serial radios.
|
Just a small suggestion for your brain care:
First of all, try to establish a reliable wired communication procedure.
After that, and only after that add the RF link.
Tell us your result.
Humberto |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Wed Oct 26, 2005 9:23 am |
|
|
Neil,
Thanks for the background. That's what I was looking for. I'm the proverbial 4 year old when it comes to C. Why? ....... Why?....... Why?
I'll work on optimization if I need to. I tend to use larger parts at higher speeds to do fairly simple things ( a technique fairly forgiving of the optimizationally challenged.)
Humberto,
Thanks for the suggestion. I normally put a serial port on every board for development. I had the radios working with a previous, non-packetized, scheme but when I made the changes it broke. Trouble shooting has been complicated by the fact the problem is with one of the radios... I think. I may have sent the radio into lala land, and I don't have a carrier board to reset it....should get one in a couple of days. I have two other radios that don't exhibit the problem.
The actual problem is:
I put a LED flash in the MAIN WHILE routine.....
Code: | if(bkbhit) { //something in RX buffer
output_high(LED3);
delay_ms(500);
output_low(LED3) |
It hangs without having TXed it anything. So I'm pairing everything done right now to retry just some simple TX and RX routines to recheck my hardware....
I'll report back.
Thanks,
John |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Wed Oct 26, 2005 10:02 am |
|
|
Update:
Bad radio.... Comms are working with simple tx and rx code. Now I'm trying to debug some packetized comms (checksum routine) with nothing but a flashing LED. Argggghhhhh.
Code: | while(TRUE) {
strike_head_on_wall();
} |
John |
|
|
|