View previous topic :: View next topic |
Author |
Message |
mk77
Joined: 08 May 2010 Posts: 6
|
yet another RS232 post |
Posted: Sat May 08, 2010 2:57 pm |
|
|
Hello all,
I am trying to write a simple program that receives a string from the RS232 and stores it for later use.
I have seen numerous examples in this forum, yet I did not succeed making any of them work for me.
I try to keep it as simple and as fast as possible...
here is the code as it is now:
Code: |
#include <input.c>
#include <stdio.h>
#include <stdlib.h>
char input [ 30 ];
int index = 0;
int1 input_ready = FALSE;
// serial interupt
#int_rda
void serial_interrupt ( )
{
if (index<29) {
input [index] = getc();
putc(input[index]);
if (input [index] == '\r') {
input_ready = TRUE;
index = 0;
break;
}
index++;
}
else index = 0;
}
void main()
{
printf("starting\n");
enable_interrupts(int_rda);
enable_interrupts(global);
while (1) {
input_ready = false;
if (input_ready) {
disable_interrupts(int_rda);
printf("plot-->%s",input);
enable_interrupts(int_rda);
}
}
}
|
I get the "starting" message in the terminal, but then nothing.
i don't even get the PUTC that I added to echo the input even before \r is detected.
any help will be most appreciated.
Moshe. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 08, 2010 4:26 pm |
|
|
Quote: |
while (1) {
input_ready = false;
if (input_ready) {
disable_interrupts(int_rda);
printf("plot-->%s",input);
enable_interrupts(int_rda);
}
}
|
Look at what your while() loop is doing. You turn off the flag, and
then you test it. It will probably fail the test. There is a small chance
that the interrupt will occur just before the if() test, and set the flag.
But normally it will fail. You need to move the top line inside the if()
block. |
|
|
mk77
Joined: 08 May 2010 Posts: 6
|
|
Posted: Sun May 09, 2010 11:37 am |
|
|
Thanks for the correction PCM, I modified the code as you suggested.
However, if you will notice the code I posted, I put inside the serial interrupt a putc to echo every getc, and that does not work either.
I've edited the serial interrupt a bit in order to debug it:
Code: |
#int_rda
void serial_interrupt ( )
{
if (index<29) {
input [index] = getc();
printf("%d\n",index);
//putc(input[index]);
if (input [index] == '\r') {
input_ready = TRUE;
index = 0;
break;
}
index++;
}
else index = 0;
}
|
I am printing the index variable each time an interrupt is fired.
once I start a run - i get the following result:
starting
0
1
and then nothing happens, regardless of what i send through the port and regardless of the terminal i use (the 2 index counts are of the letters "n" and "w", don't know where they are coming from...).
can this be a hardware fault?
thanks for the help,
Moshe. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 09, 2010 12:59 pm |
|
|
CCS has an example of how to use INT_RDA interrupts to get a string.
Look at the bget_string() function (buffered get_string) in this file:
Quote: |
c:\program files\picc\examples\ex_zmd.c
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 10, 2010 12:30 am |
|
|
Just a general comment: The program you posted is not complete.
The #fuses and processor include lines are missing, and even more importantly the '#use rs232' line is not there.
If you don't post a complete program we can not know if you left out something on purpose or if this is the root of your problem. It is amazing how many problems we detect in these first three program lines.
Also post your compiler version number always. |
|
|
mk77
Joined: 08 May 2010 Posts: 6
|
|
Posted: Mon May 10, 2010 12:52 pm |
|
|
Thanks for all the comments so far.
I use ver. 4.088 and XBEE as a serial interface.
I looked at ex_zmd and found it useful since i need many of the functions in there.
I copied them and twisted it a bit in order to suite my needs.
here is the code:
Code: |
#include "D:\programming\code\robot.h"
#include <input.c>
#include <stdio.h>
#include <stdlib.h>
#use i2c(Master,sda=PIN_C4,scl=PIN_C5)
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
#define RS232_BUFFER_SIZE 127
char rs232_buffer[RS232_BUFFER_SIZE];
int8 rs232_nextin=0, rs232_nextout=0;
#int_rda
void isr_rda(void) {
char c;
c=getc();
rs232_buffer[rs232_nextin++]=c;
if (rs232_nextin >= RS232_BUFFER_SIZE) {rs232_nextin=0;}
printf("in RDA");
break;
}
char bgetc(void) {
char c;
while (rs232_nextout==rs232_nextin) {restart_wdt();}
c=rs232_buffer[rs232_nextout++];
if (rs232_nextout >= RS232_BUFFER_SIZE) {rs232_nextout=0;}
return(c);
}
void bget_string(char* s, int max) {
int len;
char c;
--max;
len=0;
do {
c=bgetc();
if(c==8) { // Backspace
if(len>0) {
len--;
putc(c);
putc(' ');
putc(c);
}
} else if ((c>=' ')&&(c<='~'))
if(len<max) {
s[len++]=c;
putc(c);
}
} while(c!=13);
s[len]=0;
}
signed int bget_int()
{
char s[3];
signed int i;
bget_string(s, sizeof(s)-1);
i=atoi(s);
return(i);
}
signed long bget_long() {
char s[7];
signed long l;
bget_string(s, sizeof(s)-1);
l=atol(s);
return(l);
}
#define bkbhit() (rs232_nextin!=rs232_nextout)
void main()
{
char s[10];
printf("starting\n");
enable_interrupts(int_rda);
enable_interrupts(global);
while (1) {
if (bkbhit()) {
bget_string(s,sizeof(s)-1);
printf("%s\n",s);
}
}
|
I added a printf("in RDA") while inside the RDA, and the result is that the terminal is being filled with "in RDA" messages - which means it keeps coming to the RDA and never stops, even when no information is being sent.
The Xbee definitions work out fine when i check them with the AT commands.
No idea on what can go wrong...
Thanks again for the help.
Moshe.
UPDATE:
----------
the plot thickens - I changed the printf("in RDA") to printf("%s",c) so it will show me the characters he gets to the buffer ant this is what the terminal spits out:
<STX>nwA @xxx???xxx???xx<SO><STX>nwA @xxx???xxx???xx<SI><STX>nwxxx???xxx???xx<DLE><STX>nwA @xxx???xxx???xx<DC1><STX>nwA @xxx???xxx???xx<DC2><STX>nwA @xxx???xxx???<STX>nwA @xxx???xxx???xx<DC4><STX>nwA @xxx???xxx???xx<NAK><STX>nwA @xxx???x @xxx???xxx???xx<EM><STX>
and so on...
anyone has a clue?
Best regards,
Moshe |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 10, 2010 2:48 pm |
|
|
Quote: | #int_rda
void isr_rda(void) {
char c;
c=getc();
rs232_buffer[rs232_nextin++]=c;
if (rs232_nextin >= RS232_BUFFER_SIZE) {rs232_nextin=0;}
printf("in RDA");
break;
}
|
The printf inside the #int_rda will cause you to lose incoming characters.
The UART transmitter only has a "1-deep" input buffer. Therefore, it
can accept 2 characters immediately ("in"), without having to wait for the
transmitter to be ready. But the remaining 4 characters " RDA" will
require waiting for 1 ms each, for a total of 4 ms. The incoming
characters will quickly fill up the 2-deep receive buffer and overrun it,
and you will lose characters. Remove the printf from the #int_rda routine.
Also, the 'break' is unnecessary. It does nothing. Remove it. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 10, 2010 3:22 pm |
|
|
Code: | signed int bget_int()
{
char s[3]; | I reported this error in v4.099 but never got confirmed it being solved.
The 's[3]' is too small and causes the maximum range you can read to be -9 to 99 (or +9 if you use the sign). Change to 's[5]' for the full -127 to +128 range. |
|
|
mk77
Joined: 08 May 2010 Posts: 6
|
|
Posted: Wed May 12, 2010 2:18 pm |
|
|
Thanks for all the suggestions...
I'm afraid nothing helped - I focus my search on the hardware and xbee settings, maybe that's the source of the problem, though everything seems to be in order.
If anyone who knows xbee recognizes something from the output I've posted and has a suggestion, I will be more than happy to hear.
Moshe. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed May 12, 2010 4:19 pm |
|
|
The program you posted is incomplete (robot.h is missing) and looks like to have a syntax error (missing '}'). So is this the real program you are testing with?
You can remove the not used i2c line, include files, bget_int and bget_long functions. Then post the complete and small as possible program.
Describe the hardware you have connected. Brand and model number of the Zigbee modules.
Is there a MAX232 or similar driver between the Zigbee modules and the PIC?
What is the data you are sending to the PIC?
How are you sending this?
What is the data you receive? |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu May 13, 2010 4:50 am |
|
|
Check out my post on "Receiving txt messages" on the working code part of the forum...
it depends on reading and sending strings over RS232 for sms control
it might help
also i have this little code to test my USART
Code: | #if defined(__PCB__)
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000) //must be 20 MHz
#elif defined(__PCM__)
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000) //must be 20 MHz
#use rs 232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // serial
void serialint();
char key; // caracter recibido
int presente; // flag personal
void main()
{
enable_interrupts(INT_RDA); // habilitar interrupt de recieved data
enable_interrupts(GLOBAL); // habilitar interrupts globales
presente=0; // clear flag personal
while(1)
{
if(presente==1)
{
printf("%c\r\n",key); // imprimir return y new line
presente=0;
}
}
}
#INT_RDA
void serialint()
{
key=getchar();
presente = 1;
} |
keep your isr As short as possible...i just get the char and set a flag.
all echoes and proscesing you can do outside...
like pcm programer said..if you take to long inside your isr you will loss characters
try putting the incoming data in a circular buffer ....
(i use one in my previously mentioned code "recieving txt messages")
hope this helps
sorry for the spanglish on my code comments
gabriel _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu May 13, 2010 8:24 am |
|
|
I would suggest taking the XBEE out of the circuit for now and work on getting your code working with a hard wired cable first. Once you have your code working like you want THEN migrate to the wireless and start trouble-shooting it.
Printf(), puts() or delays are not good inside an ISR. ISR's should be as short as possible. If I need to monitor the progress of an ISR, I'll have an output toggled or set/cleared and then monitor that output. Much faster for the ISR.
Ronald |
|
|
rjrodrig
Joined: 09 Sep 2009 Posts: 7
|
Re: yet another RS232 post |
Posted: Thu May 13, 2010 12:27 pm |
|
|
if you put this code in the interrupt and create a buffer before main()
called RX_BUFFER
Code: |
#define RX_BUFFER_SIZE 20 //Store Command Chars
#define ArrayLength (RX_BUFFER_SIZE + 1) //+1 Stores Chars + '\0'
main()
{
}
/*
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
I S R R X I N T E R R U P T S E R V I C E R O U T I N E
PIC24HJ256GP210.
*/
#INT_RDA
void RX_SerialData_ISR(void)
{
disable_interrupts(INT_RDA); // RS232 OFF
RX_BUFFER[RX_Wr_Index] = fgetc(RS232_USB); //Get the character in the HW buffer
if(RX_BUFFER[RX_Wr_Index] == 13) //Is the current char a Carriage Return?
{ //then set the flag, and reset the Buffer pointer
RX_DONE = 1; //Set the Reception is DONE...
/*### INSERT THE NULL TERMINATOR ###*/
RX_BUFFER[RX_Wr_Index] = '\0'; //Add Null Terminator to the Buffer
RX_Wr_Index = 0; //Reset the Index back to the beginning
if(RX_BUFFER[0] == 0x21) //HALT ANY MEASUREMENT PROCESSES with "! + CR"
{
STOP_MEASURING = 1;
}
}
else if(++RX_Wr_Index == RX_BUFFER_SIZE) //Increment the index and check if we reach the Buffer limit
{
RX_DONE = 1; //Set the Reception is DONE...
/*### INSERT THE NULL TERMINATOR ###*/
RX_BUFFER[RX_Wr_Index] = '\0'; //Terminate the buffer
RX_Wr_Index = 0; //Reset the Index back to the beginning
//Parsed_RXData(); //Parse the data automatically
}
else if((RX_Wr_Index % 4) == 3)
{
U1STA &= 0xFFFD; //Clear OverRun Error OERR Errata 18
IFS0 &= 0xF7FF; //Clear Clear Interrupt Flag Errata 18
}
//clear_interrupt(INT_RDA); //Clear the interrupt Flag
enable_interrupts(INT_RDA); //Re-enable the interrupt
}
|
mk77 wrote: | Hello all,
I am trying to write a simple program that receives a string from the RS232 and stores it for later use.
I have seen numerous examples in this forum, yet I did not succeed making any of them work for me.
I try to keep it as simple and as fast as possible...
here is the code as it is now:
Code: |
#include <input.c>
#include <stdio.h>
#include <stdlib.h>
char input [ 30 ];
int index = 0;
int1 input_ready = FALSE;
// serial interupt
#int_rda
void serial_interrupt ( )
{
if (index<29) {
input [index] = getc();
putc(input[index]);
if (input [index] == '\r') {
input_ready = TRUE;
index = 0;
break;
}
index++;
}
else index = 0;
}
void main()
{
printf("starting\n");
enable_interrupts(int_rda);
enable_interrupts(global);
while (1) {
input_ready = false;
if (input_ready) {
disable_interrupts(int_rda);
printf("plot-->%s",input);
enable_interrupts(int_rda);
}
}
}
|
I get the "starting" message in the terminal, but then nothing.
i don't even get the PUTC that I added to echo the input even before \r is detected.
any help will be most appreciated.
Moshe. |
|
|
|
mk77
Joined: 08 May 2010 Posts: 6
|
|
Posted: Thu May 13, 2010 12:44 pm |
|
|
thanks for all the help and suggestions.
I know using printf and putc inside the ISR is a bad practice, the thing is that I see that the RX and TX LEDs on my robot are blinking constantly and only the RX LED on my PC's XBEE is blinking, which makes me suspect there is a hardware fault at hand.
I will try to connect with a serial cable, but it will require a bit of fiddling, since I made the entire robot architecture suitable for the XBEE (I'll probably solder a small circuit with max232 on the side).
I will keep you updated on the results, and if the problem occurs with a cable i will post the entire code, what i am sending, receiving, etc.
Pictures of the application will be posted once problem is solved
Again, thanks for helping out,
Moshe. |
|
|
mk77
Joined: 08 May 2010 Posts: 6
|
Hello, again.... |
Posted: Sat Jun 05, 2010 7:33 am |
|
|
Well, I switched from wireless Xbee communication to regular serial cable and unfortunately, the problem remains.
It seems that the controller keeps jumping into INT_RDA, even when nothing is being sent to it.
In order to rule out hardware fault (both in the controller and the board), I am looking for a proved to be working, most simple "echo" program, that listens on the RS232 port and "echoes" everything back to the terminal.
If that won't work I will change board, controller , etc. until the fault will be found.
I will be more than thankful to anyone who can refer me to such a program.
Thanks in advance,
Moshe. |
|
|
|