TOC PREV NEXT

9.2 SERIAL COMMUNICATIONS UNDER LINUX


In Linux serial communications is similar to normal file access. The file names used to access these ports are in the 'dev' directory. The 'com1' port is called 'ttyS0', and the 'com2' port is called 'ttyS1'.

#ifndef __SERIAL
#define __SERIAL
#define ERROR -1
#define NO_ERROR 0
class serial_io {
protected:
public:
int fd; /* File Descriptor Global Variable */
serial_io(char*);
~serial_io();
int decode_param(char*);
int writer(char*);
int reader(char*, int);
};
#endif

Figure X.10 - The Header File (serial_io.h)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <ctype.h>

#include "serial_io.h"


char *param_file_name;
int param_baud;
int param_parity; // not implemented yet
int param_size;
int param_flow; // not implemented yet



serial_io::serial_io(char *args){
struct termios
options;
int error;
int i;

param_file_name = NULL;
param_baud = B9600; // set defaults
param_size = CS8;
char temp[200];
int len, last, cnt;

error = NO_ERROR;
strcpy(temp, args);
len = strlen(args);
last = 0;
cnt = 0;
for(i = 0; (i < len) && (error == NO_ERROR); i++){
if(temp[i] == ','){
temp[i] = 0;
error = decode_param(&(temp[last]));
cnt++;
last = i + 1;
} else if(i == (len-1)){
error = decode_param(&(temp[last]));
cnt++;
}
}

if((error == NO_ERROR) && (param_file_name != NULL)){
if((fd = open(param_file_name /*args[0] port "/dev/ttyS0"*/, O_RDWR | O_NOCTTY | O_NDELAY)) < 0){
printf("Unable to open serial port\n");
fd = -1;
} else {
fcntl(fd, F_SETFL, FNDELAY);
/* Configure port reading */
tcgetattr(fd, &options);
/* Get the current options for the port */

cfsetispeed(&options, param_baud); /* Set the baud */
cfsetospeed(&options, param_baud);

options.c_cflag |= (CLOCAL | CREAD);
// enable receiver and set local mode

options.c_cflag &= ~PARENB;
// Mask the character size to 8 bits, no parity
options.c_cflag &= ~CSTOPB;

options.c_cflag &= ~CSIZE;
// set data size
options.c_cflag |= param_size;
// set number of data bits

// options.c_cflag &= ~CRTSCTS;
// Disable hardware flow control
// options.c_lflag &= ~(ICANON | ECHO | ISIG);
// process as raw input
options.c_oflag |= OPOST;

// Update settings
tcsetattr(fd, TCSANOW, &options);
}
} else {
fd = -1;
}
}


serial_io::~serial_io(void)
{
close(fd);
fd = -1;
if(param_file_name != NULL) delete param_file_name;
}


int serial_io::decode_param(char*parameter){
int error;
int temp;

error = NO_ERROR;
if(parameter[0] == 'F'){
if(param_file_name != NULL) delete param_file_name;
param_file_name = new char[strlen(parameter)];
strcpy(param_file_name, &(parameter[1]));
} else if(parameter[0] == 'B'){
temp = atoi(&(parameter[1]));
if(temp == 9600) param_baud = B9600;
if(temp == 2400) param_baud = B2400;
if(temp == 1200) param_baud = B1200;
} else if(parameter[0] == 'D'){
temp = atoi(&(parameter[1]));
if(temp == 8) param_size = CS8;
if(temp == 7) param_size = CS7;
} else {
printf("Did not recognize serial argument type - ignoring\n");
}

return error;
}


int serial_io::reader(char *text, int max){
int char_read,
error,
i, j;

error = ERROR;
if(fd >= 0){
char_read = read(fd, text, max-1);
if (char_read > 0){
text[char_read] = 0;
error = NO_ERROR;
for(i = 0; i < char_read;){
if((text[i] == 10 /*CR*/) || (text[i] == '\n')){
for(j = i+1; j <= char_read; j++){
text[j-1] = text[j];
}
char_read--;
} else if(text[i] == '\t'){
text[i] = ' ';
i++;
} else {
i++;
}
}
} else {
text[0] = 0;
}
} else {
printf("Serial port is not initialized\n");
}

return error;
}


int serial_io::writer(char *text)
{
int error,
length = 0,
count = 0;

error = NO_ERROR;
if(fd >= 0){
length = strlen(text);
for(count = 0; count < length; count++){
write(fd, &(text[count]), 1);
}
} else {
printf("Serial port not initialized\n");
error = ERROR;
}

return error;
}

Figure X.11 - Serial Communication Drivers (serial_io.c)

#include "serial_io.h"

main(){
serial_io *serial;
char in[100];
char sent[107];
int flag = 0;
char out[100];

serial = new serial_io("B9600,F/dev/ttyS0");
while(flag == 0){
if(serial->reader(in, 100) != ERROR){
if(strlen(in) > 0){
printf("Got String: %s", in);
sprintf(out, "ECHO: %s\n", in);
printf("Sending String: %s", out);
serial->writer(out);
}
}
}

delete serial;
}

Figure X.12 - A Serial Communication Program (serial.c)

These programs can be compiled with the makefile in Figure X.13.

all: serial
CC=g++
CFLAGS=
serial: serial.c serial_io.o
$(CC) $(CFLAGS) serial.c -o serial serial_io.o
serial_io.o: serial_io.c serial_io.h
$(CC) $(CFLAGS) -c serial_io.c

Figure X.13 - A Makefile

TOC PREV NEXT