|
|
View previous topic :: View next topic |
Author |
Message |
Allan
Joined: 20 Dec 2009 Posts: 23
|
int16 over rs232 |
Posted: Thu Mar 18, 2010 4:44 am |
|
|
Hi everybody,
I've got a beginners RS232 question. I'm using a 18f2321 with V4.104 software. I need a method to send more than a single character over RS232. I know my hardware (National 97176 rs485 drivers) is working because I can send single / receive single characters.
With "errors" removed from the #USE statement the program locks, with "errors" in place I get a bunch of 0's. I get the same type of errors when I use fprintf() instead of fputs
If I understand the manual the compiler is taking care of null terminating the strings at the atol and ltoa statements, so I didn't add a "\r"
Code: |
#use rs232(uart1, baud = 9600, Enable = EPIN, stream = Remote, errors, DISABLE_INTS)
============
#INT_RDA
void InputRS232()
{
extern int16 Display; // Send - receive an int16
char data[10];
fgets(data, Remote);
Display = atol(data);
}
============
char data[10];
itoa(Display, 10, Data);
fputs(Data, Remote);
|
Also, is there a simpler way to send an int16 over rs232? Those string functions are using a lot of resources.
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Thu Mar 18, 2010 6:54 am |
|
|
First problem. Do a search here about RS485 termination, and more importantly _bias_. It sounds as if your bus is not biased 'off', so garbage characters are being received, when it is not driven. 'ERRORS' prevents the UART from locking up, when unhandled characters are received.
Then understand the difference between '\r', and '\0'. '\r', means 'carriage return' a transmittable ASCII charcater. '\0', is the string terminator character inside the memory. The PIC will automatically add the latter to the data, when the _former_ is received. At some point though, you need to be sending a carriage return...
Then understand what the interrupt implies. It is saying there is _one_ charcater received. You are calling 'gets', inside the interrupt, which means the code will sit inside the interrupt, effectively 'hung', _until_ a carriage return is received. If more than 9 characters do arrive (the garbage for instance), then the buffer _will_ overflow, destroying the contents of memory...
So:
Code: |
#include "ex_sisr.c" //CCS's example interrupt driven receive
//Then something like
signed int16 wait_for_number(int16 loopfor) {
int16 temp=0;
int8 chr;
do {
if (bkbhit()) {
chr=bgetc();
if (chr>='0' && chr<='9') {
//Have received a number
temp=temp*10;
temp=temp+(chr-'0'); //Add in the digit
}
if (chr=='\r') {
//Have carriage return
return temp;
}
}
delay_us(90);
} while (loopfor--);
return -1L; //flag for 'timeout'
}
//Then in the main
signed int16 val;
//Ten inside your loop waiting for values
val=wait_for_number(1000); //Wait for about one second
if (val==-1) {
//Display/handle number not received
}
else {
fprintf(data,"%02LD\n\r",val);
}
|
You obviously need to put the main etc. around this.
Now, it is only a demo, but the 'wait_for_number' routine, loops for 'loopfor' times, and if text numbers are received, builds a running sum, by converting them to numeric (-'0'), and adding them to the running total *10. When the carriage return is seen (just like gets, it _needs_ this), it returns the number generated. If the loop count, gets to zero, it instead returns '-1', to say that the string didn't arrive in time.
It gives a basic idea of how to receive text nmbers, without getting involved in the string functions at all.
Best Wishes |
|
|
Allan
Joined: 20 Dec 2009 Posts: 23
|
|
Posted: Thu Mar 18, 2010 6:05 pm |
|
|
Quote: |
understand the difference between '\r', and '\0'.
|
Thanks Ttelmah!
I'll also put a scope on the data lines tomorrow - the design is proven but an IC might have been damaged by static or handling
Allan |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Thu Sep 08, 2011 9:19 pm |
|
|
I added the code to the Ex_SISR code
I get a consistent errr that I cannot find.
Executing: "C:\Program Files\PICC\Ccsc.exe" +FH "..\serial\Serial.c" +EXPORT +DF +LN +T +A +M +Z +Y=9 +EA
*** Error 58 "Serial.c" Line 16(19,20): Expecting a close paren
1 Errors, 0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Thu Sep 08 20:11:25 2011
Code: |
#include <EX_SISR.c>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)
signed int16 wait_for_number(int16 loopfor)
{
int16 temp=0;
int8 chr;
do {
if (!bkbhit())
{
chr=bgetc();
if (chr>='0' && chr<='9');
{
//Have received a number
temp=temp*10;
temp=temp+(chr-'0'); //Add in the digit
}
if (chr=='\r');
{
//Have carriage return
return temp;
}
}
delay_us(90);
} while (loopfor--);
return -1L; //flag for 'timeout'
}
main()
{
signed int16 val ;
enable_interrupts(global);
enable_interrupts(int_rda);
val=wait_for_number(1000); //Wait for about one second
if (val==-1) {
//Display/handle number not received
}
else {
fprintf(seriale,"%02LD\n\r",val);
}
while (TRUE);
}
|
I neeed a better pair of eyes. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 08, 2011 9:34 pm |
|
|
Quote: | if (chr>='0' && chr<='9');
if (chr=='\r'); |
Your if() statements all have semi-colons at the end. Remove them. |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Thu Sep 08, 2011 9:40 pm |
|
|
Semicolons removed but no joy. I get the same error! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 08, 2011 9:42 pm |
|
|
Post the current code and mark the line that the error is on,
so I can easily see it. Your post said "line 19", but which one
is that ? Mark it with a comment. |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Thu Sep 08, 2011 10:11 pm |
|
|
Code: |
#include <EX_SISR.c>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)
signed int16 wait_for_number(int16 loopfor)
{
int16 temp=0;
int8 chr;
do {
[b]if (!bkbhit())[/b] { "This is line 16"
chr=bgetc();
if (chr>='0' && chr<='9')
{
//Have received a number
temp=temp*10;
temp=temp+(chr-'0'); //Add in the digit
}
if (chr=='\r')
{
//Have carriage return
return temp;
}
}
delay_us(90);
} while (loopfor--);
return -1L; //flag for 'timeout'
}
main()
{
signed int16 val ;
enable_interrupts(global);
enable_interrupts(int_rda);
val=wait_for_number(1000); //Wait for about one second
if (val==-1) {
//Display/handle number not received
}
else {
fprintf(seriale,"%02LD\n\r",val);
}
while (TRUE);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 08, 2011 10:36 pm |
|
|
This code can't compile. You can't take the Ex_sisr.c example file, which
has it's own #fuses, and main(), and tack another test program with
it's own main(), etc., onto the end of it.
Just delete the #include for Ex_sisr.c, and put in the #include line for
your PIC. Then copy and paste everything from Ex_sisr.c except for
the initial part of that file, which has the lines for the PIC, #fuses, etc.,
and put it just after the #use rs232() line in your program. You just
want the "guts" of the Ex_sisr.c file (variable declarations and functions).
In the line above in your posted code, you have two parentheses after
the bkbhit. Get rid of those.
Also get rid of the stream parameter in your own #use rs232() line.
The Ex_sisr.c routines are not setup to use a stream.
If you do all that, it should compile. |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Thu Sep 08, 2011 11:52 pm |
|
|
Got it to compile. Not getting the correct result. It should show the value of the numbers typed. It only shows the last 2 digits once, then hangs
Code: |
#include<18F2620.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#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 !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
signed int16 wait_for_number(int16 loopfor)
{
int16 temp=0;
int8 chr;
do {
if (!bkbhit)
{
chr=bgetc();
if (chr>='0' && chr<='9') {
//Have received a number
temp=temp*10;
temp=temp+(chr-'0'); //Add in the digit
}
if (chr=='\r') {
//Have carriage return
return temp;
}
}
delay_us(90);
} while (loopfor--);
return -1L; //flag for 'timeout'
}
main()
{
signed int16 val ;
enable_interrupts(int_rda);
#if defined(__PCD__)
enable_interrupts(intr_global);
#else
enable_interrupts(global);
#endif
printf("\r\n\Running...\r\n");
val=wait_for_number(1000); //Wait for about one second
if (val==-1) {
//Display/handle number not received
fprintf(seriale,"%02LD\n\r",val);
}
else {
fprintf(seriale,"%02LD\n\r",val);
}
while (TRUE);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Sep 09, 2011 8:25 am |
|
|
Add 'errors' to the use rs232(...) option list, that'll take care of the UART buffer being full and clobbered by more incoming. |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Fri Sep 09, 2011 8:40 am |
|
|
Added "errors" to the RS232 but still the same result. If I type in 4 numbers only the last two digits show and it hangs. It seems so simple. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 09, 2011 12:45 pm |
|
|
You came into this thread, but I don't think you ever told us what you
want to do. Do you want to get an unsigned decimal integer consisting
of up to 4 digits, with the digits in ASCII format, which will arrive at the
PIC over the RS-232 interface ?
And, how will the number be terminated ? Will it have a Carriage Return
(0x0D) character at the end ?
If you want anything different than that, such as signed instead of
unsigned, or if you want more (or less) digits, or if it's not in decimal,
or if there is no termination byte, or anything else, please tell us. |
|
|
wgalaugher
Joined: 10 Jan 2011 Posts: 18
|
|
Posted: Fri Sep 09, 2011 1:11 pm |
|
|
Good lesson for me. Never make any assumptions about what people think you mean.
What I trying to do with this code is to type in 4 digit via RS232 with a carriage return so the PIC will assemble these digits into an int16 numeric variable that I can use as a control value in the program. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 09, 2011 3:13 pm |
|
|
Look at the get_long() function in this CCS driver file:
Quote: |
c:\program files\picc\drivers\input.c
|
If you want an interrupt-driven buffered version of it, look at:
Quote: |
c:\program files\picc\examples\ex_zmd.c
|
It's for get_int(), but it could be modified for get_long(). |
|
|
|
|
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
|