View previous topic :: View next topic |
Author |
Message |
deltatech
Joined: 22 Apr 2006 Posts: 87
|
Reading a Block of ascii characters from UART |
Posted: Wed Sep 09, 2009 11:01 pm |
|
|
I want to read a block of ascii numbers that is sent by the PC to my PIC.
Can any one please tell me what I am doing wrong. I have tried the following code but is is not working.
The size of the data block is fixed to 768 bytes always, as below:
Code: |
01 0130 0131 1230 1231 1430 1400 0130 0131 1230 1231 1430 1400
02 0230 0231 0330 0331 1830 1831 0230 0231 0330 0331 1830 1831
03 0330 0331 0430 0431 1930 1931 0330 0331 0430 0431 1930 1931
04 0430 0431 0530 0531 2030 2031 0430 0431 0530 0531 2030 2031
05 0530 0531 0630 0631 2130 2131 0530 0531 0630 0631 2130 2131
06 0630 0631 0730 0731 2230 2231 0630 0631 0730 0731 2230 2231
07 0730 0731 0830 0831 2330 2331 0730 0731 0830 0831 2330 2331
08 0830 0831 1030 1031 0330 0331 0830 0831 1030 1031 0330 0331
09 0930 0931 1330 1331 1530 1531 0930 0931 1330 1331 1530 1531
10 1030 1031 0230 0231 0530 0531 1030 1031 0230 0231 0530 0531
11 1130 1131 1230 1231 0630 0631 1130 1131 1230 1231 0630 0631
12 1030 1031 1430 1431 2330 2331 1030 1031 1430 1431 2330 2331
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <input.c>
//======================================
void main()
{
char temp[769]; size of the data block
printf("Enter string: ");
get_string(temp, sizeof(temp));
printf("\n\rReceived: %s \n\r", temp);
while(1);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 09, 2009 11:11 pm |
|
|
Quote: | #include <16F877.H>
char temp[769]; size of the data block |
It's not working because it doesn't compile. You didn't even try to
compile it. The PCM compiler can't make a RAM array larger than the
bank size, and that's a maximum of of 96 bytes for the 16F877.
(Even if you use #device *=16). |
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
|
Posted: Wed Sep 09, 2009 11:29 pm |
|
|
Thanks PCM Programmer
I Have tried it with pic18f6622 and still it wont work
Code: | #include <18F6622.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <input.c>
//======================================
void main()
{
char temp[768];
//printf("Enter string: ");
get_string(temp, sizeof(temp));
printf("\n\rReceived: %s \n\r", temp);
while(1);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 09, 2009 11:41 pm |
|
|
Quote: |
void get_string(char* s, unsigned int8 max) {
unsigned int8 len;
|
Look at the definition of the get_string() function in input.c.
CCS has declared the 'max' and 'len' variables as an int8.
To go larger than 255 bytes, you would have to change them
to int16. If you do that, it would be best to make a copy of
the get_string() function and put it in your program. Then
modify that copy. Don't include the input.c file. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 10, 2009 9:30 am |
|
|
curiosity talking here:
do you have any time-out or other protection method in mind to prevent a total hang of the program should the full 768 bytes not be received?
as in what happens if you DON't get to fill the full string ?
or to get back in sync if you DO manage to survive a bad length string receive ?
just wondering if this was for fun or for real
|
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
|
Posted: Thu Sep 10, 2009 12:26 pm |
|
|
Hi Pcm Programmer
Is this the best to way read a block of 768 byte ascii characters from the uart? Do you have any example you can suggest? I have searched on the forum. There are many posts but I can't find one where someone read a block of text from the UART.
Hi asmboy. I am sorry I am newbee I don't have any timeout protection. This is for real not just fun. I want to read the table above. This is 768 bytes big and it is fixed. It doesn't change. It is to be read from a PC connected to the pic serial port. I would be grateful if you would help me by making any suggestions that would get me started. Many thanks. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 10, 2009 1:48 pm |
|
|
In the middle of my work day now but will post you code later this evening (lcl time).
The way I do that is to set up a circular ring buffer, serial interrupt handler.
And then poll an INT_KBhit() function to see if there are characters ready - and remove them - checking and appending to the output_768 char string as you get them - even checking for "legality" ( not line-faulted ) as I go.
Then there is never the chance for a hang - and I can do other tasks while I wait for all the chars to arrive ( or not arrive as the case may be ).
ciao till later |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
ISR receiver that buffers chars as they arrive |
Posted: Thu Sep 10, 2009 5:31 pm |
|
|
Code: |
// serial port ISR parts 96 byte buffer for 18F use
// this example is for 38400 and at max throughput
// you need not remove a char for up to 25 msec to avoid overflow,data loss
// if you DO overflow - the pointers wrap , but don't crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
// TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)
// NB: ONLY call if bkbhit is true
// ignore this at your peril
char bgetc(void) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(risr_out);
}
void DISR_INIT(void){ // prepare handler
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // the handler
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 protection !!
}
// in your Main ( just fragmentary here
main (){
// your init stuff
disr_init();
while (1){
// other stuff you need to cycle through
//
// below will not execute unless chars wating in the INT buffer
while ( bkbhit ) { // LOOP as long as chars are in ISR buffer
your_next_char=bgetc(); // unloads one char from buffer
// check, append or whatever your new char NOTE RISR_OUT global
} // your keyhandler ends NOTE: no wait for a char to come in
// other stuff you want to do AFTER some new chars are found and handled
} // you main loop ends
} // main ends
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
ISR receiver that buffers chars as they arrive |
Posted: Thu Sep 10, 2009 5:33 pm |
|
|
Code: |
// serial port ISR parts 96 byte buffer for 18F use
// this example is for 38400 and at max throughput
// you need not remove a char for up to 25 msec to avoid overflow,data loss
// if you DO overflow - the pointers wrap , but don't crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
// TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)
// NB: ONLY call if bkbhit is true
// ignore this at your peril
char bgetc(void) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(risr_out);
}
void DISR_INIT(void){ // prepare handler
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // the handler
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 protection !!
}
// in your Main just fragmentary here
main (){
// your init stuff
disr_init();
while (1){
// other stuff you need to cycle through
//
// below will not execute unless chars are waiting in the INT "buffer"
while ( bkbhit ) { // LOOP as long as chars are in ISR buffer
your_next_char=bgetc(); // unloads one char from buffer
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends NOTE: no wait for a char to come in
// other stuff you want to do AFTER some new chars are found and handled
} // you main loop ends
} // main ends
|
|
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
|
Posted: Thu Sep 10, 2009 8:14 pm |
|
|
Hi asmboy thanks for your help with this problem.
I have tried to adopt your code to my application to the best of my ability, but unfortunately I get an error message on compilation on the following line of code:
buffer+=next_char[i]; //build the 768 bytes received form the UART
What I am trying to do is rebuild the received table one byte at a time but I think I am doing something wrong.
Please point out my mistake. Many Thanks.
Code: |
// serial port ISR parts 96 byte buffer for 18F use
// this example is for 38400 and at max throughput
// you need not remove a char for up to 25 msec to avoid overflow,data loss
// if you DO overflow - the pointers wrap , but don't crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 769
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
// TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)
// NB: ONLY call if bkbhit is true
// ignore this at your peril
char bgetc(void) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(risr_out);
}
void DISR_INIT(void){ // prepare handler
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // the handler
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 protection !!
}
// in your Main just fragmentary here
main (){
unsigned int8 next_char[679];
BYTE buffer[679];
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);
setup_oscillator(False);
// your init stuff
disr_init();
while (1){
// other stuff you need to cycle through
//
// below will not execute unless chars are waiting in the INT "buffer"
while ( bkbhit ) {
char i; // LOOP as long as chars are in ISR buffer
for (i=0;i<769;i++)
{
next_char[i]=bgetc(); // unloads one char from buffer
buffer+=next_char[i]; //build the 768 byte received form the UART one byte ata time
}
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends NOTE: no wait for a char to come in
// other stuff you want to do AFTER some new chars are found and handled
} // you main loop ends
} // main ends
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 10, 2009 9:01 pm |
|
|
TYPOS and syntax
DON'T try to use the background and count it out
leave the SIZE of buffer code alone - as set originally
have a buffer for received and do this:
it's much simpler than U r trying to make it
Code: |
// stay with BUFFER_SIZE =96 !! dont mess with the vars directly that the // INT handler touches - you will be glad you did it that way
char Yourbuffer [770] // your assembly point for the fished out 768
yourbuffer[769]=0; // making sure of null \0 terminator char
int16 bufptr=0; // fill point
// so starting and assuming read w/o checking chars
// and later
while ( bkbhit && bufptr<768) {
yourbuffer[bufptr++]=bgetc(); // unloads 1 char
}
// test when bufptr shows 768 recvd && process YOURBUFFER
// then reset bufptr=0; wyen ready to get another
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends
|
|
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
|
Posted: Thu Sep 10, 2009 10:26 pm |
|
|
Hi asmboy thanks for your help i think i have more understanding now where i am going you hav been great help thanks .
But when i compile the new code i get an erro at the following line
yourbuffer [769]=0; // making sure of null \0 terminator char
the error is
Code: |
// if you DO overflow - the pointers wrap , but don't crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
char yourbuffer [770] ; // your assembly point for the fished out 768
yourbuffer [769]=0; // making sure of null \0 terminator char
int16 bufptr=0; // fill point
// so starting and assuming read w/o checking chars
BYTE next_in = 0;
BYTE next_out = 0;
// TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)
// NB: ONLY call if bkbhit is true
// ignore this at your peril
char bgetc(void) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(risr_out);
}
void DISR_INIT(void){ // prepare handler
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // the handler
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 protection !!
}
// in your Main just fragmentary here
main (){
// your init stuff
disr_init();
while (1){
// other stuff you need to cycle through
//
// below will not execute unless chars are waiting in the INT "buffer"
while ( bkbhit && bufptr<768)
{ // LOOP as long as chars are in ISR buffer
yourbuffer[bufptr++]=bgetc(); // unloads 1 char//your_next_char=bgetc(); // unloads one char from buffer
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends NOTE: no wait for a char to come in
//-----------
/// and later
// test when bufptr shows 768 recvd && process YOURBUFFER
// then reset bufptr=0; wyen ready to get another
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends
//-----------
// other stuff you want to do AFTER some new chars are found and handled
} // you main loop ends
//} // main ends
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 10, 2009 10:30 pm |
|
|
The code is FRAGMENTARY - not a compilable program - incomplete
not all done and ready to fly by any means.
It illustrates the principle of serial INT Buffering ,
in your special case - and that was all.
But now you have to understand how to write a c- program
to finish the job and write the program you mentioned. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Sep 11, 2009 5:09 pm |
|
|
this is a MINIMAL !!! version that will compile and shows mistakes
starting with the #device line that does not belong
there is LOTS'A work to do to make this a complete program
but go forth and prosper and best wishes
Code: |
// serial port ISR parts 96 byte buffer for 18F use
// this example is for 38400 and at max throughput
// you need not remove a char for up to 25 msec to avoid overflow,data loss
// if you DO overflow - the pointers wrap , but don't crash
#include <18F6620.h>
// ## FUSES statement needed HERE !!
#use delay( clock=8000000 ) // clock changed to 80000
char yourbuffer[780]; // your assembly point for the fished out 768
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
int16 bufptr=0; // fill point
// so starting and assuming read w/o checking chars
BYTE next_in = 0;
BYTE next_out = 0;
// TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)
// NB: ONLY call if bkbhit is true
// ignore this at your peril
char bgetc(void) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(risr_out);
}
void DISR_INIT(void){ // prepare handler
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // the handler
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 protection !!
}
// in your Main just fragmentary here
main (){
yourbuffer[778]=0;
// your init stuff
disr_init();
while (1){
// other stuff you need to cycle through
//
// below will not execute unless chars are waiting in the INT "buffer"
while ( bkbhit && bufptr<768)
{ // LOOP as long as chars are in ISR buffer
yourbuffer[bufptr++]=bgetc(); // unloads 1 char//your_next_char=bgetc(); // unloads one char from buffer
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends NOTE: no wait for a char to come in
//-----------
/// and later
// test when bufptr shows 768 recvd && process YOURBUFFER
// then reset bufptr=0; wyen ready to get another
// check, append or whatever new char NOTE RISR_OUT global
} // your keyhandler ends
//-----------
// other stuff you want to do AFTER some new chars are found and handled
} // you main loop ends
//} // main ends
|
|
|
|
|