|
|
View previous topic :: View next topic |
Author |
Message |
Antoine1973
Joined: 14 Apr 2012 Posts: 3
|
Serial communication with 18F4550 |
Posted: Sat Apr 14, 2012 2:54 pm |
|
|
Hi all,
To make a long story short, I try to read data from a EM406 GPS module.
This guy continuously sends ascii frames to the serial port.
When you connect the GPS to Hyperterminal (4800-N-1) you can see the message content with position and so on.
I wrote a small piece of code(see below) to grab that message, without success :-(
I tested my serial comm code by sending messages from Hyperterminal to the PIC and there, it works fantastic !
After spending a while testing hardware, baud rate and others basics, I came down to the conclusion that the only difference between the reception from the GPS (that doesn't work) and the reception from Hyperterminal (that works OK) is the fact that the GPS continuously poors a large amount of data to the UART, while Hyperterminal send one character at the time.
This issue of "jamming" the serial port appears on many posts, but despite the helpful tips I found there (the "ERROR" command in the RS232 setting, #INT_RDA interrupt,...) it still doesnt' work !
Is there something more I can do OR do I just reach the limit of what this chip can do ???
Keep in mind that I have no possibility to change the way the GPS module outputs its data.
Thanks for reading
Antoine
Code: |
#INT_RDA
void serial_isr()
{
char cara;
output_toggle(led4);
cara = getc();
if ((RS232_ERRORS & 6)!=0) return;
putc(cara);
}
void main(){
char c;
// Clear the USART receive register and its fifo
// by reading it three times.
c = RCREG;
c = RCREG;
c = RCREG;
enable_interrupts(global);
enable_interrupts(INT_RDA);
while(TRUE)
{
delay_ms(1);
output_toggle(led3);
}//fin du main
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Apr 14, 2012 3:08 pm |
|
|
First, if the UART is hung, reading the buffer _will not clear the condition_. The UART has to be turned 'off', and then 'on' again. Use getc in your boot code.
So:
Code: |
void main(void){
char c;
// Clear the USART receive register
while (kbhit()) c = getc();
|
When you add 'ERRORS' to the #USE RS232 line, code is added to the _getc_, to automatically do this and clear the error once triggered.
You don't show your RS232 setup line, so we cannot verify that you have added errors to this.
With this done, you don't need to add anything to do with RS232_ERRORS to your INT_RDA. You only need to read RS232_ERRORS, if you want to do something about errors if they happen.
Realistically, you don't show your code 'using' the value you have read. Assuming something here takes _time_, your INT_RDA, needs to be actually buffering the data (sending it to a larger storage area until you can do something with it EX_SISR.c shows how to do this.
Seriously you don't tell us your clock rate, so comments about what the chip can do, are unanswerable, _but_ to put it into perspective, I have systems logging data from a GPS, and writing data to an SMS, when the unit gets within a specified distance of a target, together with reading other parameters like temperature, using a very basic PIC at 4MHz, and not even working terribly hard.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Antoine1973
Joined: 14 Apr 2012 Posts: 3
|
|
Posted: Sat Apr 14, 2012 3:51 pm |
|
|
Ttelmah: thx a lot for your advices:
// Clear the USART receive register
while (kbhit()) c = getc();
Helped a lot.
BTW: #use rs232(baud=4800,STOP=1, BITS=8, PARITY=N, ERRORS, UART1) |
|
|
Antoine1973
Joined: 14 Apr 2012 Posts: 3
|
|
Posted: Sun Apr 15, 2012 3:42 am |
|
|
Hello all,
It works ! FYI code below.
For Lextronic GPS users: I had to insert a buffer between the GPS output and the RX pin of the pic. The 3V output is too weak to trigger the input pin.
Topic closed.
Code: |
#include <18F4550.h>
//configure a 20MHz crystal to operate at 48MHz (USB High speed)
#fuses NOWDT,NOPROTECT,NOLVP,NODEBUG
#fuses PLL5 // Divide 20MHz crystal to feed 4MHz to the PLL
#fuses HSPLL
#fuses CPUDIV1 // PLL Postscaler divides by 2 ==> Primary clock = 48 MHz
#fuses USBDIV // Use clock from PLL
#fuses VREGEN // Enables 3.3V
#use delay(clock=48Mhz) // 48 MHzPrimary Clock comes from PLL Postscaler
#use rs232(baud=4800,STOP=1, BITS=8, PARITY=N, ERRORS, UART1) //baud=5050
#define led1 PIN_A2 //mode LED1
#define led2 PIN_A4 //curseur ++ ou -- LED2
#define led3 PIN_A3 //memorisation LED3
#define led5 PIN_E0 //bit de vie LED5
#define led4 PIN_A5 //LED4
#include <string.h>
char trame[5];
int i;
char message[21];
char cara;
#INT_RDA
void serial_isr()
{
cara = getc();
if (cara == '$') {output_toggle(led4); }
}
void main(){
char c;
while (kbhit()) c = getc();
enable_interrupts(global);
enable_interrupts(INT_RDA);
while(TRUE)
{
delay_ms(10);
output_toggle(led3);
putc(cara); // echoes out the received character
//output_bit(PIN_A5,input(PIN_C7));
}
}//fin du main
|
|
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Sun Apr 15, 2012 6:11 pm |
|
|
Hi,
Well, you've solved, one of your problems, the hardware one, but your code still does nothing useful.
BTW, the hardware issue is that the PIC Rx input is a schmitt trigger input, and has different threshold requirements than other PIC inputs. The original 3V signal was not sufficient to reliably trip the input!
For your code, I suggest you look at ex_sisr.c in the examples folder to see how to implement an interrupt driven circular serial buffering system. Such a scheme is probably the only reliable means to receive asynchronous serial data.
John |
|
|
|
|
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
|