Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics 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
 

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
 

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.
 

According sugestion by horace follows a pseudo-code example :

Value = getc(data) ;
Value += ( getc(data)<<8 ) ;


+++
 

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!).
 

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.
+++
 

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.
 

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

+++
 

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
 

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
 

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) ;
 

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.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top