View previous topic :: View next topic |
Author |
Message |
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
from circular buffer to signed int16 |
Posted: Tue Jan 21, 2014 2:14 pm |
|
|
Hi,
The function i want to develop should update the value of a signed int16 variable every time there is a new value from the rs232 (terminated with CR).
I receive correctly and store in a circular buffer (ex_SISR.C).
Queston is: How should I organise the program to do this?
I guess I have to:
- check in the isr if I receive a CR: set a flag.
- Read the flag from the main, and de-load the buffer with bgetc() filling a character array. value[10]
- Then use atol. (does it work for signed int??) and empty the character array. (how? value='';??) |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jan 22, 2014 3:14 am |
|
|
In your previous post you sorted out how to do a circular buffer.
Can I encourage you to take a similar approach again.
Have a go, ask questions with your code, if/when you get stuck.
Someone will gladly help if you show you've put in the effort.
You'll also learn a lot more.
Best of luck.
Mike
PS In the time which has elapsed since your post you could have had a least one try. |
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Wed Jan 22, 2014 1:00 pm |
|
|
I'll give it a go |
|
|
dorinm
Joined: 07 Jan 2006 Posts: 38
|
|
Posted: Wed Jan 22, 2014 5:08 pm |
|
|
Usually you use a circular buffer when you don't have enough time to process all the incoming data and need a buffer (that's what really is, nothing more).
If you want to update a var every time you read a new value you need a much simpler aproach, I think (something like read the first byte in a temp. var, then wait for "some" time for the second byte (could use a simple state machine or something), if it arrives, make a int16 and update your variable, reset the state machine.....)... my 2 cents... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Jan 22, 2014 7:34 pm |
|
|
code snippet....
Code: | signed int16 x;
int8 vhi=0;
int8 vlo=0;
void main() {
while(true){
delay_ms(5000);
vhi=0x12;
vlo=0x34;
x=make16(vhi,vlo);
printf("\n\r%02x %02x %0ld ",vhi,vlo,x);
vhi=0x92;
vlo=0x34;
x=make16(vhi,vlo);
printf("\n\r%02x %02x %0ld ",vhi,vlo,x); |
x1234= 4660
x9234= -28108
vhi, vlo would be the bytes from your serial input.
I would suggest a 'marker' of some kind to be sure the data received is in correct order!
hth
jay |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Jan 22, 2014 7:44 pm |
|
|
test program
OK, ain't pretty but it does work...
Code: | //46k22 test program
#include <18f46k22.h>
#include "46k22_fuses.h"
#include "46k22_pins.h"
#use delay(clock=16000000)
#use rs232(baud=9600, UART2, ERRORS,stream=u2)
//===============================
signed int16 x;
int8 vhi=0;
int8 vlo=0;
void main() {
while(true){
vhi=fgetc(U2);
vlo=fgetc(U2);
x=make16(vhi,vlo);
printf("\n\r%02x %02x %0ld ",vhi,vlo,x);
}//end of forever while
}//end of main program
|
sent data by Realterm as 0x12 0x34 , then 0x92 0x34
hth
jay |
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Tue May 27, 2014 2:27 pm |
|
|
Hi,
I understand your code but I don't understand how to apply it to my case.
I send from hyperterminal to the PIC a command like MF=123 terminated with CR. I store it in a circular buffer (an array of characters).
So, I have an array that at the index 4 5 6 has the characters of the number I want to put into an int16 (or int8 would be ok also). I don't see the "high" and "low" byte. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue May 27, 2014 2:46 pm |
|
|
You are sending ASCII text, not binary values. It was the latter that temtronic assumed.
Look at 'atol' in the manual. Write the characters into an array. When you see the CR, write a '\0', and then call atol with the address of the array. It does the conversion to int16. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue May 27, 2014 2:48 pm |
|
|
webgiorgio wrote: | Hi,
I understand your code but I don't understand how to apply it to my case.
I send from hyperterminal to the PIC a command like MF=123 terminated with CR. I store it in a circular buffer (an array of characters).
So, I have an array that at the index 4 5 6 has the characters of the number I want to put into an int16 (or int8 would be ok also). I don't see the "high" and "low" byte. |
That's because you have not got the "high" and "low" bytes.
In your case of MF=123 followed by CR, you've got ASCII characters '1' '2' '3' at indicees 4,5,6 in the buffer.
You convert your ASCII characters to binary then to int16.
(Or use the built in ASCII to int16 conversion.)
Mike
EDIT
Mr T. got in whilst I was typing.
Last edited by Mike Walne on Tue May 27, 2014 2:49 pm; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue May 27, 2014 2:49 pm |
|
|
Ok NOW you've changed the data.....
originally I assumed you were receiving the int16 data as 2 bytes..
Now though,you'll have to 'parse' your buffer which contains 'MF=123', looking for the '=' the grab the next 3 bytes( 123 ).
Those I assume are 'one hundred and twenty three'.
From there you'll have to 'convert' and place into an int16 variable.
hint...decimal 123 is 7B in hex
problem though...an int16 can hold up to 65535, so your 'incoming data' might be 65 thousand,five hundred and thirty five...so you'll need to grab the next 5 bytes(if present) after the equal sign.
hint. if you 'pad' the data to always have 5 bytes it might be easier for you to decode.
hth
jay |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue May 27, 2014 2:59 pm |
|
|
Hi,
I'd forget the 'circular' buffer as it unnecessarily complicates a simple project. A 'linear' buffer is more than adequate - start buffering when you receive the 'M' character, and stop when you receive the <CR> character.
Now, keep in mind that the buffer will contain the ASCII values for the digits you've sent. You'll need to convert those ASCII values to their decimal equivalents. I use a routine like this for that purpose:
Code: |
// This routine is used to convert characters for checking the checksum
// It simply converts an ASCII hex value into true decimal form
// ASCII allows for a quick and dirty conversion routine!
byte gethexbyte(char digit) {
if(!BIT_TEST(digit,6)) // Its a number if bit 6 is 0
return(digit & 0x0F); // Simple way to convert 0-9
else
return((digit & 0x0F) + 9);
}
|
Here is one way you could 'decode' the example command string (eg. 'MF=123') you've provided:
Code: |
Value = (gethexbyte(RxBuffer[3]) * 100) + (gethexbyte(RxBuffer[4]) * 10) + (gethexbyte(RxBuffer[5]));
|
Hopefully this gives you what you are missing!
John |
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Wed May 28, 2014 3:10 am |
|
|
sorry for the misunderstanding. Yes I send ASCII characters to the PIC serial port from hyperterminal. And yes temtronic, 123 i mean 'one hundred and twenty three' (or any other value 0-255). I will try atol().
But, is a string an array of characters?? |
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Wed May 28, 2014 4:14 am |
|
|
Code: | if (data_ready){ //read cmd_string and empty buffer
data_ready=0;
i=1;
printf("\r\nBuffered data => ");
//memset(cmd_string,0,sizeof(cmd_string));
cmd_string[0]=0; //empty the array
while((data_in_buffer)){
cmd_string[i]=buffer_getc();
putc(cmd_string[i]);
i++;
}
cmd_string[i]='\0';
printf("\nstring= %s\n", cmd_string);
} |
data_ready is set to 1 when the ISR receives a '\r' character.
I sent something to the pic, "MF=123" or "test", whatever string. I see it printed back from the putc(), but not from the printf(). ...why?
Quote: | ***** booting... ******
test
Buffered data => test
string=
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed May 28, 2014 4:50 am |
|
|
At first glance your code looks OK.
It is difficult to say why printf doesn't work because you didn't post a complete test program.
Is it possible you have multiple '#use RS232' lines?
printf() by default uses the last '#use RS232' line it encounters. To avoid these problems it is better to use fprintf() and a stream name: Code: | #use RS232 (uart1, baud=9600, stream=SERIAL_PC)
fprintf(SERIAL_PC, "Test\n"); |
|
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Wed May 28, 2014 5:49 am |
|
|
I solved! it was the way I initialized the string.
Code: | strcpy(cmd_string, ""); //empty the array |
works |
|
|
|