Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Read data from serial port

Status
Not open for further replies.

sydb

Newbie level 3
Joined
Mar 21, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
qro
Activity points
1,311
I want to read a 16 bit data from the serial port,
I´m thinking on reading 2 bytes from serial port to make them a single value but i don´t know how. Is there any other way to read the 16 bit data. Or anyone have an example to do this

I´m using pic 16f876a and i´m using mikroc. Thanks
 

horace1

Advanced Member level 5
Joined
Nov 18, 2008
Messages
2,123
Helped
596
Reputation
1,188
Reaction score
573
Trophy points
1,393
Location
Norwich, UK
Activity points
13,071
you can split a 16bit value into two bytes so
Code:
      int data= 0x1234;
      unsigned char lsb=data & 0xff;
      unsigned char msb=(data >> 8) & 0xff;
msb should = 0x12 and lsb = 0x34
reverse the shift operation and add the two bytes to get the 16 bit data back
make sure that both the UART and the PC are both set for 8 data bits

you could always change the data to a character string and send that - converting from a string to an int at the other end
 

sydb

Newbie level 3
Joined
Mar 21, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
qro
Activity points
1,311
Thanks for reply, but how do I read the 2 consecutive bytes from the serial port?
I can only read 1 byte at the time.
 

horace1

Advanced Member level 5
Joined
Nov 18, 2008
Messages
2,123
Helped
596
Reputation
1,188
Reaction score
573
Trophy points
1,393
Location
Norwich, UK
Activity points
13,071
Re
Code:
Value = getc(data) ;
Value += ( getc(data)<<8 ) ;
make sure you transmit the bytes in the correct order so that you can form the integer using the above code, i.e. you have the endianness correct. Also if you are sending signed data check that the word lengths are the same on both machines or explicitly take account of the different word lengths. I would recommend working in shorts ints as these are usually 16 bit (two bytes) whereas ints can be 16, 32 or 64 bytes depending on the system being used (always worth checking though!).
 

andre_teprom

Super Moderator
Staff member
Joined
Nov 7, 2006
Messages
9,221
Helped
1,147
Reputation
2,313
Reaction score
1,123
Trophy points
1,403
Location
Brazil
Activity points
53,681
Really you pointed an important sight.
Sydb must remember to mark the border of transmitions data prefereably with some ASCII character.
The code portion above can be improved like that :
if ( ( data != '\r' ) | ( data != '\n' ) )
{
Value = getc(data) ;
Value += ( getc(data)<<8 ) ;
}

Course integers sent must have a separator like carriage return between each one.
+++
 

horace1

Advanced Member level 5
Joined
Nov 18, 2008
Messages
2,123
Helped
596
Reputation
1,188
Reaction score
573
Trophy points
1,393
Location
Norwich, UK
Activity points
13,071
Really you pointed an important sight.
Sydb must remember to mark the border of transmitions data prefereably with some ASCII character.
the problem with using seperators such as \n and \r in binary data is what happens if binary data values have the same code ? it can terminate the transmission early. To transmit binary data I would create a frame either with frame length at the start and count character received or using start and end flags with character stuffing, in both cases using a checksum or CRC check for error detection.
 

andre_teprom

Super Moderator
Staff member
Joined
Nov 7, 2006
Messages
9,221
Helped
1,147
Reputation
2,313
Reaction score
1,123
Trophy points
1,403
Location
Brazil
Activity points
53,681
Horace

According your valuables observations follow code piece corrected

if ( ( data != '\r' ) | ( data != '\n' ) )
{
Value = ( getc('39'-data) <<0 )* 0x000F ;
Value += ( getc('39'-data) <<4 ) * 0x00F0;
Value += ( getc('39'-data) <<8 ) * 0x0F00;
Value += ( getc('39'-data) <<12 ) * 0xF000;
}

Now the constraint is that all data bytes bust be sent in ASCII format with format example :
['1']['2']['3']['4']['\n'] ==> 1234 DEC

+++
 

horace1

Advanced Member level 5
Joined
Nov 18, 2008
Messages
2,123
Helped
596
Reputation
1,188
Reaction score
573
Trophy points
1,393
Location
Norwich, UK
Activity points
13,071
is 16 bits realy required? e.g. if data is from a 10 or 12 ADC you only need to send 10 or 12 bits not 16.
This is some sample code from a program where I was sending 12 bit signed data encoded as two characters, the first character holding bits 8 to 11 and the second character bits 0 to 7. This data was mixed in with normal 7 bit ASCII so bit 7 of the first character is set to 1 to indicate integer binary data (in normal ASCII bit 7 was 0). This application was a dsPIC33 using 16 bit signed ints sending data to a PC using 32 bits signed ints so the sign bit has to be extended
Code:
// encode a 12 bit signed integer into 2 characters
// bit 7 of first character is 1 to indicated encoded data
void RSencode(unsigned char data[2], int idata)
{

     data[0]=  0x80 | ((idata>>8)&0x0f) ;   // top 4 bits of data
     data[1]= idata & 0xff;                // lower 8 bits of data
}

// decode the above data, return 1 for sucess else 0
int RSdecode(unsigned char data[2], int *idata)
{
    if(! (data[0] & 0x80)) return 0;       // NOT encoded data
    *idata= ((data[0] << 8) & 0x0f00) | (data[1] & 0xff) ;
    // sign extend to 32 bit integer
    if(*idata & 0x800) *idata |= 0xfffff000;
    return 1;
 }

int main()
{
   int data =1100, data1, data2=-1100;
   unsigned char ch[2];
   RSencode(ch, data);
   if(RSdecode(ch, &data1)) printf("result = %d\n", data1);
   else                     printf("decode failed\n");
   RSencode(ch, data2);
   if(RSdecode(ch, &data1)) printf("result = %d\n", data1);
   else                     printf("decode failed\n");
}
if I run the simple test program I get
Code:
result = 1100
result = -1100
these days I useEthernet or WiFi to sent UDP datagrams or USB
 

sydb

Newbie level 3
Joined
Mar 21, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
qro
Activity points
1,311
Hi, I Found that with the an interruption and read the RCREG I can store the 8 bit data into a variable1 with the next interruption store the next byte into variable2.
The question is if variable 1 is lsb and variable2 is msb how can i join them to make a single value, because it´s not clear for me.

Thanks
 

horace1

Advanced Member level 5
Joined
Nov 18, 2008
Messages
2,123
Helped
596
Reputation
1,188
Reaction score
573
Trophy points
1,393
Location
Norwich, UK
Activity points
13,071
shift the msb left 8 bits and OR it with the lsb
e.g. something along the lines of
Code:
   short int  i= ((variable2 << 8) & 0xff00) | (variable1 & 0xff) ;
 

RuH_iranga

Junior Member level 3
Joined
Nov 4, 2010
Messages
31
Helped
7
Reputation
14
Reaction score
6
Trophy points
1,288
Location
sri lanka
Activity points
1,480
you can joint them exactly from above post. shifting MSB's from several bits can be done by multipling 2^n . where n=no of shifting bits.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top