View previous topic :: View next topic |
Author |
Message |
isv10
Joined: 29 Aug 2010 Posts: 15
|
Can't receive '\0' null character in serial(rs232) |
Posted: Tue Jul 17, 2018 5:13 am |
|
|
Hello. My project with pic16f1829.
Receiving string with int_rda but can't detect null \0 char.
Someone has a comment ?
#define BUFFER_SIZE 32
int1 have_string=FALSE;
char string[BUFFER_SIZE];
int index=1;
#int_rda
void serial_isr() {
char c;
c=getc();
if(c=='\0')
{
have_string=true;
string[index]=c;
return;
}
string[index]=c;
if(index >= BUFFER_SIZE)
index=index-1;
else
index++;
printf("H");
}
void main()
{
setup_wdt(WDT_1S); //~2.0 ms reset
restart_wdt();
// setup_adc_ports(sAN2|sAN4|sAN5);
// setup_adc(ADC_CLOCK_DIV_2);
//setup_timer_2(T2_DIV_BY_1,4,1); //1.0 us overflow, 1.0 us
enable_interrupts(global);
enable_interrupts(int_rda);
restart_wdt();
output_high(PIN_C7);
delay_ms(500);
output_low(PIN_C7);
delay_ms(500);
output_low(PIN_C7);
//printf("test code");
restart_wdt();
while(TRUE)
{
restart_wdt();
if(have_string)
{
puts(string);
have_string=FALSE;
}
}
}[/b] |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9253 Location: Greensville,Ontario
|
|
Posted: Tue Jul 17, 2018 5:31 am |
|
|
general comments..
1) no #use RS232(...options...) Pre prosessor directive. That's kinda important
2) delete all the WDT related code. NOT required
3) no #include device header. That's kinda required too !
4) use the [code] button( top center of this page) when posting code. Really helps us 'see' the code !
5) you'll need to add 'ERRORS' to the missing #Use RS232(...) options
Probably more but coffee's ready !
Jay |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 5:48 am |
|
|
Thanks for your reply.
This code works fine but can't detect '\0' null char. When i send test string with PC and return it with puts() in int_rda it works good. But when i want to control string with the following code it can't detect '\0'.
Code: |
#include <16F1829.h>
#device ADC=10
#include <string.h>
#include <stdlib.h>
#FUSES WDT //Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=16MHZ,restart_wdt)
#use rs232(baud=9600,xmit=PIN_B7,rcv=PIN_B5,UART1,RESTART_WDT)
#use pwm(CCP1,FREQUENCY=40000)
#define BUFFER_SIZE 32
int1 have_string=FALSE;
char string[BUFFER_SIZE];
int index=1;
#int_rda
void serial_isr() {
char c;
c=getc();
if(c=='\0')
{
have_string=true;
string[index]=c;
return;
}
string[index]=c;
if(index >= BUFFER_SIZE)
index=index-1;
else
index++;
printf("H");
}
void main()
{
//setup_wdt(WDT_1S); //~2.0 ms reset
restart_wdt();
// setup_adc_ports(sAN2|sAN4|sAN5);
// setup_adc(ADC_CLOCK_DIV_2);
// setup_timer_2(T2_DIV_BY_1,4,1); //1.0 us overflow, 1.0 us interrupt
enable_interrupts(global);
enable_interrupts(int_rda);
restart_wdt();
output_high(PIN_C7);// for test
delay_ms(500);
output_low(PIN_C7);
delay_ms(500);
output_low(PIN_C7);
restart_wdt();
while(TRUE)
{
restart_wdt();
if(have_string)
{
puts(string);
have_string=FALSE;
}
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9253 Location: Greensville,Ontario
|
|
Posted: Tue Jul 17, 2018 6:26 am |
|
|
OK, now get rid of the WDT AND add 'errors' to the USE RS232.
The WDT is 'about 2ms', probably +-50-100%, so it could be tripping at 1ms...
hmm...9600 baud is 'about' 1 character per 1ms
so it is possible the WDT is resetting the PIC.
Without the 'ERRORS' option, the HW UART will lockup after the 2-3 characters. Now I don't use that PIC and don't know IF the HW UART is being used. If it is a 'software' UART, then the ISR won't work....
Jay |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 6:46 am |
|
|
Thanks for your help. I test WDT change. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19561
|
|
Posted: Tue Jul 17, 2018 6:49 am |
|
|
First, learn to use the code buttons....
Code: |
#define BUFFER_SIZE 32
int1 have_string=FALSE;
char string[BUFFER_SIZE];
int index=1; //This is wrong. Remember your array starts at 0....
#int_rda
void serial_isr(void) {
char c;
c=getc();
if(c=='\0')
{
have_string=true;
string[index]=c;
return;
}
string[index]=c;
if(index >= BUFFER_SIZE)
index=index-1;
else
index++;
printf("H");
}
|
Except for the error of having the index starting at 1, not 0, this will basically work.
There is another issue though on index. Imagine it is 31. You test. It is not>=BUFFER_SIZE, so it is incremented to 32. The next time the interrupt executes you are writing to string[32], which will result in values being corrupted as this is beyond the end of the array.....
Code: |
if(++index >= BUFFER_SIZE)
index=index-1;
|
This avoids this problem. Incrementing before the test.
However the question is how you are sending the '\0'?. Remember a string printed from C, will not send the null terminator normally.... |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 7:22 am |
|
|
Hello Ttelmah and thanks for your help. I changed index=1 and forget to correct it. I send string from pc to micro (with serial port terminal) and then try to find '\0' from end of string. But when i send for example 3 char string, program return (HHHH) or send 5 char string it return (HHHHHH). It means i have 4 interrupt for 3 char string, and 6 interrupts for 5 char string. I want to detect end of string. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19561
|
|
Posted: Tue Jul 17, 2018 7:29 am |
|
|
Are you absolutely sure your program is sending the NULL?.
Terminal programs etc., normally won't. If you send a string with something like sendln, it prints the string, and then a line feed, not a NULL...
You need to find out what your source program is actually sending.
It is extremely rare for PC programs to actually print the NULL.
Put it in perspective, CCS won't either.
If you print a string with:
printf("%s", string);
The NULL won't be printed. |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 7:40 am |
|
|
How can i find it ? I try with '\n' and no response. When i send string from terminal, for example (test) string i receive (HHHHHtest)
and for another string in new line receive... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9253 Location: Greensville,Ontario
|
|
Posted: Tue Jul 17, 2018 7:42 am |
|
|
Post the name of the 'terminal program' on the PC. Should be easy to figure out how to add the null to the transmitted data...
Jay |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 7:59 am |
|
|
Serialport Terminal
by coad.net |
|
|
isv10
Joined: 29 Aug 2010 Posts: 15
|
|
Posted: Tue Jul 17, 2018 11:51 pm |
|
|
Hi. Problem was solved.
Windows is backward compatible with MS-DOS and used the CR-LF convention because MS-DOS was compatible with CP/M-80 which used the CR-LF convention because that was how you drove a printer (because printers were originally computer controlled typewriters).
The result is in Windows based terminal, send '\r\n' or '\n' end of string. Thus i use '\r' in my program and it works very good!!!!!!!!!!!!!!!! |
|
|
|