View previous topic :: View next topic |
Author |
Message |
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
First character on getc is Null - Buffer not clearing in dbg |
Posted: Sun Apr 29, 2012 4:43 pm |
|
|
I am using get_string functionality in an attempt to get a 22 character response. I am using the debug windows - specifically the Monitor window - to send the data. Using getc in a for loop it always captures or puts a null character first in line then the data I enter. I can remove it but I do not believe this is proper operation and don't want this to be unstable. Here is my code:
Code: |
#include <16F690.h>
#include <string.h>
#include <ctype.h>
#use delay (internal=4mhz)
#fuses INTRC_IO, MCLR, NOCPD
#use RS232(DEBUGGER, xmit=PIN_B7, RCV=PIN_B7) //DEBUG
// Global Variables
int i;
int BTS[23];
int string1[6];
void get_string(char* s, unsigned int8 max)
{
unsigned int8 len=0;
char caddr;
for (len=0;len<max;len++)
{
caddr=getc();
s[len]=caddr;
}
return;
}
void BT_WRITE()
{
get_string(BTS, 23);
printf("\n\r\%s\n\r","Complete"); //Confirm receipt of entire message
printf("%s\n\r",BTS); //Print captured characters
return;
}
void main()
{
BT_WRITE();
}
|
When I run the program, I enter the characters in the Monitor screen of the debug window. The BTS variable always shows the first character to be a null '\0' then my characters I enter are shown.
Anyone have suggestions of how to prevent the null as the first entry?
Thank you.
Last edited by schmez on Fri May 04, 2012 9:33 am; edited 1 time in total |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Sun Apr 29, 2012 6:42 pm |
|
|
Are you using a RS485 converter or something that could put a Start bit spike on the line? I would put a scope on the line and look for a spurious Start bit before the real data. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
no external interface |
Posted: Sun Apr 29, 2012 7:47 pm |
|
|
I am using the debug in the ccs software. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Apr 30, 2012 2:02 am |
|
|
I'd suggest modifying your get_string function, to ignore null characters.
It sounds as if the debug, is replicating pretty precisely what you are likely to see in the real world. Remember that a TTL serial line at the PIC, idles 'high'. When a chip is first switched on, the line will be low for a while, till the buffer (max 232 etc.), 'wakes up'. This low, will almost certainly result in a garbage character (more often than not the line rises during the character, so 'null' is not what is seen).
Hence, adding a delay at the start of the code, and not switching on the UART, till the incoming line is seen to go high is often the 'better' solution, in real code.
Another possibility, is are you sure it is sending the null before the string - could it instead be sending a null after the string, which you haven't read, so next time you go to read it is waiting for you....
There is one glaring problem with the code. You allocate 23 characters of storage for 'BTS'. Then read 23 characters (0...22). There is then no space to add a terminating null to this, so what is stored here is _not_ a 'string', and will give problems when you print it. A 'string' in C, is a _null terminated_ sequence of characters....
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Mon Apr 30, 2012 5:20 am |
|
|
If it's the first and only the first 'character' then it's just 'garbage' from the UART buffer on powerup. Normal but easy to fix.
You should have a routine to 1st initialize the UART(use rs232(...) , then purge it's contents (read 3 times,discard the data), then clear out the BTS() array(buffer)
This way any 'garbage' data is gone and only 'real' data from the device will be sent to the buffer.
The same holds true for all variables you create. On powerup they can contain 'garbage'. The ZeroRam function nicely handles that. You should always set 'defaults' to all variabes you use. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Apr 30, 2012 8:46 am |
|
|
Yes.
The normal 'init', should be something like:
Code: |
while (input(PIN_B7)==0) ; //wait for the RS232 RX line to go _high_
while (kbhit()) getc(); //Flush the garbage character(s)
|
Obviously with the pins/stream (if used) changed to suit.
I normally also delay on boot, setting up the UART in #use RS232, with 'BAUD=0', and then after about 10mSec, then use setup_uart to turn it on. On 99% of systems, this is enough to prevent the null character.
Best Wishes |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
Still issue |
Posted: Wed May 02, 2012 10:38 pm |
|
|
Thank you all for the input - I have tried all the suggestions and I still have the same issue of the first character being null. Here is my updated code:
Code: |
#include <16F690.h>
#include <string.h>
#include <ctype.h>
#use delay (internal=4mhz)
#fuses INTRC_IO, MCLR, NOCPD
#use RS232(DEBUGGER, xmit=PIN_B7, RCV=PIN_B7, DEBUGGER) //DEBUG
// Global Variables
int i;
int BTS[24];
int string1[6];
void get_string(char* s, unsigned int8 max)
{
unsigned int8 len=0;
char caddr;
while (kbhit()) getc(); //clear buffer
for (len=0;len<max;len++)
{
caddr=getc();
s[len]=caddr;
}
return;
}
void BT_WRITE()
{
get_string(BTS, 23);
printf("\n\r\%s\n\r","Complete"); //Confirm receipt of entire message
printf("%s\n\r",BTS); //Print captured characters
return;
}
void main()
{
BT_WRITE();
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Thu May 03, 2012 1:38 am |
|
|
You have missed most of the suggestions/points.
First your get_string function is still not returning a string _null terminator_.
Second, no delay.
Third, the delays and flushing want to be before you call your get_string function, as part of the wake up procedure.
No test for the level of the line.
etc. etc..
Best Wishes |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
Update - Fix |
Posted: Thu May 03, 2012 7:24 am |
|
|
Thank you for your responses. I apologized as I did not post the latest code properly - guess that is what I get for working so late on it. Here is the correct code that does have the suggestions - the key one was looking avoiding null characters.
Code: |
#include <16F690.h>
#include <string.h>
#include <ctype.h>
#use delay (internal=4mhz)
#fuses INTRC_IO, MCLR, NOCPD
#use RS232(DEBUGGER, xmit=PIN_B7, RCV=PIN_B7, DEBUGGER) //DEBUG
// Global Variables
int i;
int BTS[24];
int string1[6];
void get_string(char* s, unsigned int8 max)
{
unsigned int8 len=0;
char caddr;
while (kbhit()) getc(); //clear buffer
for (len=0;len<max;len++)
{
caddr=getc();
if (caddr !='\0')
s[len]=caddr;
else
len--;
}
s[24]='\0'; //add terminating null
return;
}
void BT_WRITE()
{
get_string(BTS, 23);
printf("\n\r\%s\n\r","Complete"); //Confirm receipt of entire message
printf("%s\n\r",BTS); //Print captured characters
return;
}
void main()
{
while (TRUE)
{
if (input(PIN_A1) == 1) //switch to trigger
{
output_high(PIN_C2); //turn on LED
while (kbhit()) getc(); //clear buffer
delay_ms(100);
BT_WRITE();
output_low(PIN_C2); //turn off led - complete
}
}
} |
Thank you all again - now to add a timeout period. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Thu May 03, 2012 8:00 am |
|
|
Haven't looked at anything else, but:
s[24]='\0'; //add terminating null
What are the allowable index values in BTS?......
(Hint a 24 element array _does not allow you to write to an element numbered '24'......).
Best Wishes |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
Missed that |
Posted: Thu May 03, 2012 10:09 am |
|
|
Thank you- I missed that on the count - I was not counting obviously correctly. Funny as I was posting I have it working all of the sudden it stopped working - the buffer never clears properly - hoping might be the cause of it. |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
clear buffer not working |
Posted: Thu May 03, 2012 10:34 am |
|
|
Ok - sorry for the lack of expertise here - but i narrowed the issue being the buffer is not being cleared - I am using the TX/RX of RS232 on the PIC and the UART on and off does not seem to effect this either. Any other suggestions to clear the receive buffer before I start capturing data?
Or is this just a issue using the debugger? I am thinking I need to move to looking at a serial sniffer to see if this is really an issue.
Again - all your help is appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 03, 2012 12:44 pm |
|
|
I was browsing this thread and I noticed one thing that everyone didn't
see. He's using a software UART. He has the same pins defined for
xmit and rcv and in that case, the compiler will make a software UART:
Quote: |
#use RS232(DEBUGGER, xmit=PIN_B7, RCV=PIN_B7, DEBUGGER) //DEBUG
|
This is the first part of the #use rs232() code. It's definitely a software UART:
Code: |
0009: BSF STATUS.RP0
000A: BCF TRISB.TRISB7
000B: BCF STATUS.RP0
000C: BCF PORTB.RB7
000D: MOVLW 08
000E: MOVWF @21 // Initialize bit counter to 8
000F: GOTO 010
0010: NOP
0011: BSF @21.7 // Set flag for start bit (I assume)
0012: GOTO 021
0013: BCF @21.7
0014: RRF @48,F // Rotate data byte right by 1 bit
0015: BTFSC STATUS.C
0016: BSF PORTB.RB7
0017: BTFSS STATUS.C
0018: BCF PORTB.RB7 |
If you try to use the setup_uart() function with a software UART, you
will get an error. I did that and got this:
Quote: | *** Error 12 "pcm_test.c" Line 37(11,12): Undefined identifier -- setup_uart |
|
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
Software UART |
Posted: Thu May 03, 2012 1:48 pm |
|
|
Yes - you are correct, I am using the debugger included in PCW and requires the XMIT and RCV to be the same. My actual application has them separate. Is this my problem on the buffer? |
|
|
schmez
Joined: 14 Jun 2011 Posts: 24 Location: St. Louis
|
KBHIT and debugger |
Posted: Fri May 04, 2012 11:56 am |
|
|
Here is a response from support:
KBHIT is not going to work right with the DEBUGGER mode.
It will always show FALSE.
An alternative is to use #USE RS232( ICD, xmit=PIN_A0, rcv=PIN_A1 )
You will not be able to use the debugger at the same time however.
It was just the debugger - works in the actual application. |
|
|
|