View previous topic :: View next topic |
Author |
Message |
javick82
Joined: 12 Jul 2007 Posts: 43
|
Interrupts on the serial port |
Posted: Thu Jul 12, 2007 4:13 pm |
|
|
I am looking for a way to detect when an input is received from a robot, connected via RS232, into my 18f97j60 microcontroller on the picdem.net 2 board. I can talk to the robot ok, but it just won't talk back. It doesn't help that my proficiency with ISRs is not up to snuff.
Thanks! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 13, 2007 1:25 pm |
|
|
1. What character(s) the robot will be sending to the PIC ?
2. Are you using the hardware UART on the PIC to talk to the robot ? |
|
|
javick82
Joined: 12 Jul 2007 Posts: 43
|
|
Posted: Mon Jul 16, 2007 7:18 am |
|
|
The robot should send an 18 digit hexadecimal string back to the microcontroller when the position is queried. I have been working with the kbhit() function and have found that it does not recognize the hexadecimal string with the kbhit function. I can confirm that the string is making it to the microcontroller as I checked with an oscilloscope but I guess I just don't know how to have the microcontroller interpret the signal via serial port.
Thanks for your help in advance. |
|
|
Guest
|
|
Posted: Mon Jul 16, 2007 4:16 pm |
|
|
javick82 wrote: | The robot should send an 18 digit hexadecimal string back to the microcontroller when the position is queried. I have been working with the kbhit() function and have found that it does not recognize the hexadecimal string with the kbhit function. I can confirm that the string is making it to the microcontroller as I checked with an oscilloscope but I guess I just don't know how to have the microcontroller interpret the signal via serial port.
Thanks for your help in advance. |
When the hardware uart in the PIC is used, the kbhit() function tells you when a byte has been received and is waiting in the 2-byte input buffer to be retrieved by a getc() function. The INT_RDA interrupt can be enabled during your powerup initialization. It takes a fair amount of code to create a receive buffer in user-ram but CCS provides an example of such.
You can avoid using interrupts...
If your PIC sits in a loop such as while (!kbhit()); waiting to receive a byte or if it repetively polls kbhit() faster than the time it takes to receive a byte, then you can follow it with getc(). So long as you never allow the PIC to fail to empty the receive buffer, you won't miss incoming data.
When a software uart is used, all the kbhit() function really does is indicate the presence of the active state of the serial input pin. If you've been polling kbhit() fast enough, then it'll indicate the leading edge of a start bit and you can follow this with a getc() and that will receive the incoming byte. Be aware that the #use_rs232 directive doesn't create receive or transmit buffers and it won't collect data for you while your program is doing other things. All it does is set up the special function registers to enable the hardware uart or provide the software serial byte receive and transmit routines with proper bit delays built-in. The rest is up to you. |
|
|
javick82
Joined: 12 Jul 2007 Posts: 43
|
|
Posted: Tue Jul 17, 2007 7:22 am |
|
|
Quote: | You can avoid using interrupts...
If your PIC sits in a loop such as while (!kbhit()); waiting to receive a byte or if it repetively polls kbhit() faster than the time it takes to receive a byte, then you can follow it with getc(). So long as you never allow the PIC to fail to empty the receive buffer, you won't miss incoming data. |
This is what I have used, but still to no avail. I suspected there was a either a timing or buffer problem and have used the following:
Code: | while (!kbhit())
{
}
getc(); |
to clean the buffer out as handshake characters (0's) confirming commands are received.
If the buffer is indeed only 2 bytes thats 4 digits of my 18 digit hexadecimal string that is received at a 19200 baud rate. Would this present a problem for receiving the data? |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Tue Jul 17, 2007 8:44 am |
|
|
Is there a reason you can't use the ISR? That's the best way to detect if there's data coming in and will ensure that you don't miss anything in case the PIC is off doing other things when the data arrives.
ISR's aren't that hard to use. There are bunches of examples for RS232 on the board.
Ronald |
|
|
javick82
Joined: 12 Jul 2007 Posts: 43
|
|
Posted: Tue Jul 17, 2007 9:14 am |
|
|
Should the ISR be used with kbhit()? Should I use it at all times (I receive a handshake character after a command is executed by the robot)? Or only activate the ISR when I want to query the position of the robot and use kbhit() to process the handshake characters?
I have used the following ISR as well:
Code: |
#ISR_RDA
char interrupt_RDA()
{
//receiving code here
return(char); //where char is a 9 byte string, 3 for each axis
}
|
I think I will go back and try to use a combination of the 2 and see what happens. |
|
|
Bill Boucher
Joined: 04 Feb 2005 Posts: 34 Location: Chatham,ON,CA
|
|
Posted: Tue Jul 17, 2007 9:21 am |
|
|
FYI, I wrote the July 16 response as Guest. I wasn't logged in.
You quoted this code:
Quote: |
Code:
while (!kbhit())
{
}
getc(); |
Beware that the software version of #use_RS232 has no buffer at all. The hardware version uses PIC hardware that has a 2 byte buffer and the hardware performs the receive regardless of what your program is doing. The software version has to do the reception by itself so your program must be dedicated to that task. So, your getc() above, when called, will hang forever until it sees a start bit (or any leading edge), then it will basically bit-bang the byte in. I assume that you wanted the code placed within the while loop to run until there is a true kbhit() result. This would work but remember that, especially with software use_rs232, that your program has to poll kbhit() at a frequency fast enough to make the test at least 4 (to 10) times per bit time in order to sync accurately enough with the start bit to sample correctly. The while loop condition kbhit() will only be tested once at the bottom of the loop so any and all code within the loop must run & finish first before kbhit() is checked. If you are running at 19200 bits per second, your kbhit() has to be polled at least 4x faster than that or you will likely get reception errors. That's a check every 1/(4x19200) = 13 us. Yikes, that's not much time for your code within your loop to execute.
I suggest that you slow things down, a lot, like maybe down to 1200 and see if that helps. |
|
|
javick82
Joined: 12 Jul 2007 Posts: 43
|
|
Posted: Tue Jul 17, 2007 12:01 pm |
|
|
After this discussion and through my own findings, I am concerned the timing and buffer size are largely to blame for my problems.
Is there a means to increase the buffer size? You said it was in the hardware, so I doubt it. Unfortunately I can only drop the Baud rate down to 9600 on the robot.
Thanks for all the help. |
|
|
grasspuddle
Joined: 15 Jun 2006 Posts: 66
|
|
Posted: Tue Jul 17, 2007 12:15 pm |
|
|
I don't see if you said if you're using a hardware uart or not. If you are using a hardware uart then use the isr function. Look to the examples CCS gave you for code that uses the isr to store into a buffer which you can choose which size it is.
If it is software, then using the slowest baud possible will help with your kbhit() function. What speed is the 18f running at? Increasing the speed will help the code run through faster and catch the higher baud speed.
Timing will be an issue for software uarts. Definately my biggest issue when I work with software uarts. |
|
|
javick82
Joined: 12 Jul 2007 Posts: 43
|
Thanks! |
Posted: Tue Jul 17, 2007 1:51 pm |
|
|
All this discussion really helped me pinpoint the problem. It was a buffer problem and just bumping down the Baud to 9600 seems to have solved it.
Thank you all for your help. |
|
|
|