I am writing some code to talk to a device via a serial port. I am testing my program by using a loopback, so I can see that what I send is correct.

I am sending an unsigned hex array, and when I display the values (before they are sent), they are fine. However, when the array comes back, values over 7F (127) are not correct. For instance, if I send FA (which is 250), it comes back as 7A (122). But if I send 7A, it comes back as 7A so there is no way to differentiate.

I tried using a regular array (e.g. not specifying signed/unsigned) and values over 7F are negative (which would be fine, I can just add 256) but then it also comes back as 7A (122).

Any idea why this is? I am new to C so please excuse me if this is some simple and fundamental part of arrays or hex in C that I am unaware of.


Who knows, unless you post your actual code.
Perhaps you've got the serial port set to 7-bit characters, so the MSB is stripped.

Set to 8N1. Here is my code (sorry for not posting, just wondering if there was some easy thing I was missing).


 * Main.cpp
 *  Created on: 9-Jan-2009
 *      Author: root

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

#include "serprt.h"

int fd;

int initport(int fd) {
	struct termios options;
	// Get the current options for the port...
	tcgetattr(fd, &options);
	// Set the baud rates to 115200...
	cfsetispeed(&options, B115200);
	cfsetospeed(&options, B115200);
	// Enable the receiver and set local mode...
	options.c_cflag |= (CLOCAL | CREAD);

	//No parity - 8N1
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag &= ~CRTSCTS;
	options.c_cflag |= CS8;

	// Set the new options for the port...
	tcsetattr(fd, TCSANOW, &options);
	return 1;

int main(int argc, char **argv) {

	fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

	if (fd == -1) {
		perror("open_port: Unable to open /dev/ttyS0 - ");
		return 1;
	} else {
		fcntl(fd, F_SETFL, 0);
		//fcntl(fd, F_SETFL, FNDELAY);
	printf("baud=%d\n", getbaud(fd));
	printf("baud=%d\n", getbaud(fd));

	unsigned char sCmd[13]; //[254];
	sCmd[0] = 0x02;
	sCmd[1] = 0xFA; //Turn on radio
	sCmd[2] = 0x00;
	sCmd[3] = 0x00;
	sCmd[4] = 0x00;
	sCmd[5] = 0x00;
	sCmd[6] = 0x00;
	sCmd[7] = 0x00;
	sCmd[8] = 0x01;
	sCmd[9] = 0x23;
	sCmd[10] = 0x01;
	sCmd[11] = 0x21;
	sCmd[12] = 0x03;

	if (!writeport(fd, sCmd, 13)) {
		printf("write failed\n");
		return 1;

	//printf("write cmd:%d\n", sCmd[1]);
	unsigned char sResult[13];
	fcntl(fd, F_SETFL, FNDELAY); // don't block serial read

	if (!readport(fd,sResult)) {
		printf("read failed\n");
		return 1;
	//printf("readport=%d\n", sResult[1]);
	return 0;

And also serprt.c:

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int writeport(int fd, unsigned char *chars, int numBytes) {
	//int len = strlen(chars);
	//chars[len] = 0x0d; // stick a <CR> after the command
	//chars[len+1] = 0x00; // terminate the string properly
	//show array contents
	printf("write array contents:\n");
	printf("0 is: %d \n", chars[0]);
	printf("1 is: %d \n", chars[1]);
	printf("2 is: %d \n", chars[2]);
	printf("3 is: %d \n", chars[3]);
	printf("4 is: %d \n", chars[4]);
	printf("5 is: %d \n", chars[5]);
	printf("6 is: %d \n", chars[6]);
	printf("7 is: %d \n", chars[7]);
	printf("8 is: %d \n", chars[8]);
	printf("9 is: %d \n", chars[9]);
	printf("10 is: %d \n", chars[10]);
	printf("11 is: %d \n", chars[11]);
	printf("12 is: %d \n", chars[12]);
	int n = write(fd, chars, numBytes); //strlen(chars));
	if (n < 0) {
		fputs("write failed!\n", stderr);
		return 0;
	//printf("array length is %d.\n", strlen(chars));
	return 1;

int readport(int fd, unsigned char *result) {
	int iIn = read(fd, result, 254); //13); //254);
	//struct timeval timeout;
	//int iIn = select(fd + 1, result, NULL, NULL, &timeout);
	printf("Got back %d much stuff.\n", iIn);
//	//show result array
	int counter = 0;
	while(counter < 12) { //iIn) {
		printf("result[%d] is: %d\n", counter, result[counter]);
//	char* str = result[1]; //"0xFA";
//	int value;
//	char* junk;
//	value = strtol(str+2,&junk,16); 
//	printf("value is: %d\n", value);
	//result[iIn-1] = 0x00;
	if (iIn < 0) {
		if (errno == EAGAIN) {
			printf("SERIAL EAGAIN ERROR\n");
			return 0;
		} else {
			printf("SERIAL read error %d %s\n", errno, strerror(errno));
			return 0;
	return 1;

int getbaud(int fd) {
	struct termios termAttr;
	int inputSpeed = -1;
	speed_t baudRate;
	tcgetattr(fd, &termAttr);
	/* Get the input speed.                              */
	baudRate = cfgetispeed(&termAttr);
	switch (baudRate) {
		case B0:      inputSpeed = 0; break;
		case B50:     inputSpeed = 50; break;
		case B110:    inputSpeed = 110; break;
		case B134:    inputSpeed = 134; break;
		case B150:    inputSpeed = 150; break;
		case B200:    inputSpeed = 200; break;
		case B300:    inputSpeed = 300; break;
		case B600:    inputSpeed = 600; break;
		case B1200:   inputSpeed = 1200; break;
		case B1800:   inputSpeed = 1800; break;
		case B2400:   inputSpeed = 2400; break;
		case B4800:   inputSpeed = 4800; break;
		case B9600:   inputSpeed = 9600; break;
		case B19200:  inputSpeed = 19200; break;
		case B38400:  inputSpeed = 38400; break;
		case B115200:  inputSpeed = 115200; break;
	return inputSpeed;

And finally serprt.h:

#ifndef MAIN_H_
#define MAIN_H_

int writeport(int fd, unsigned char *chars, int numBytes);
int readport(int fd, unsigned char *result);
int getbaud(int fd);

#endif /*MAIN_H_*/

Does it have something to do with signed/unsigned? It seems to be ignoring my unsigned declarations and stripping off 128 from values over 127.

If I send out anything under 128 (0 to 127) it comes back as is. But if I send anything over 127 (128 to 255) it strips off 128.

It seems to maybe be stripping the 8th bit off. Maybe its not taking the setting:

options.c_cflag |= CS8;

A couple of suggestions.
1. tcsetattr returns a result, see what it is.
2. call tcgetattr afterwards (again) to see if all the changes you asked for have been made.

1. tcsetattr returns 0.
2. How do I display what the settings are? I tried this but just got an integer:

struct termios chk_options;
	tcgetattr(fd, &chk_options);
	printf("options.c_cflag = %d\n", chk_options.c_cflag);

struct termios chk_options;
tcgetattr(fd, &chk_options);
if(chk_options.c_cflag & CS8) printf("Eight bit mode\n");

A list of the other flags are here (11.2.4 Control Modes)