您的位置:首页 > 运维架构 > Linux

Simple linux serial port programming in C.

2015-04-02 13:00 429 查看
It is very often to use minicom, putty and gtkterm.. and so forth program to communicate the other device by serial port.

  It is interest to know how to use c code to control the serial port.

My C code be below:

/*refer to
* http://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c * http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <fcntl.h>
#include <termios.h> /*termio.h for serial IO api*/

#include <pthread.h>    /* POSIX Threads */

#define MAX_STR_LEN       256

/*
* The values for speed are
* B115200, B230400, B9600, B19200, B38400, B57600, B1200, B2400, B4800, etc
*
*  The values for parity are 0 (meaning no parity),
* PARENB|PARODD (enable parity and use odd),
* PARENB (enable parity and use even),
* PARENB|PARODD|CMSPAR (mark parity),
* and PARENB|CMSPAR (space parity).
* */

int SetInterfaceAttribs(int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0) /* save current serial port settings */
{
printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
return -1;
}

cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);

tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK;         // disable break processing
tty.c_lflag = 0;                // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0;                // no remapping, no delays
tty.c_cc[VMIN]  = 1;            // read doesn't block
tty.c_cc[VTIME] = 0;            // 0.5 seconds read timeout

tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;

if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
return -1;
}
return 0;
}/*set_interface_attribs*/

void SetBlocking(int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0)
{
printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
return;
}

tty.c_cc[VMIN]  = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
}/*SetBlocking*/

void *sendThread(void *parameters)
{
char sendBuff[MAX_STR_LEN];

memset(&sendBuff[0], 0, MAX_STR_LEN);
snprintf(&sendBuff[0], MAX_STR_LEN, "hello!");

int fd;

fd = *((int*)parameters);

while(1)
{
write(fd, &sendBuff[0], strlen(&sendBuff[0]) );

// sleep enough to transmit the length plus receive 25:
// approx 100 uS per char transmit
usleep((strlen(&sendBuff[0]) + 25) * 100);

usleep(500*1000);
}/*while*/

pthread_exit(0);
}/*sendThread */

void *readThread(void *parameters)
{
char readBuff[MAX_STR_LEN];

int fd;

fd = *((int*)parameters);

while(1)
{
ssize_t len;

memset(&readBuff[0], 0, MAX_STR_LEN);

len = read(fd, &readBuff[0], MAX_STR_LEN);

if (-1 == len)
{
switch(errno)
{
case EAGAIN:
printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);
usleep(5*1000);
continue;
break;

default:
printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);
pthread_exit(0);
break;
}
}

if(0 == len)
{
printf("devic is lost!\n"); /*device maybe be unplugged*/
exit(0);
}/*if*/

// sleep enough to transmit the length plus receive 25:
// approx 100 uS per char transmit
usleep((len + 25) * 100);
printf("len = %d\n", (int)len);

int i;

for(i = 0; i< len; i++)
printf("%c(%d %#x)\t", readBuff[i], readBuff[i], readBuff[i]);

printf("\n");
}/*while*/

pthread_exit(0);
}/*readThread */

int main(int argc, char *argv[])
{
int fd, c, res;
struct termios oldtio,newtio;
char buf[MAX_STR_LEN];
int k;
char deviceName[MAX_STR_LEN];

memset(&deviceName[0], 0, MAX_STR_LEN);
snprintf(&deviceName[0], MAX_STR_LEN, "/dev/ttyUSB0");

k = 1;
while(argc > k)
{
if(0 == strncmp(argv[k], "-d", MAX_STR_LEN))
{
if(k + 1 < argc)
{
snprintf(&deviceName[0], MAX_STR_LEN, "%s", argv[k + 1]);
}
else
{
printf("error : -d should be follow a device!\n");
return 0;
}/*if */
}
k++;
}/*while k*/

printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);

//non-blocking mode
//fd = open(&deviceName[0], O_RDWR | O_NOCTTY |O_NONBLOCK| O_NDELAY);

fd = open(&deviceName[0], O_RDWR | O_NOCTTY);
if(0 > fd)
{
perror(&deviceName[0]);
exit(-1);
}/*if */

SetInterfaceAttribs(fd, B115200, 0); /* set speed to 115,200 bps, 8n1 (no parity)*/
SetBlocking(fd, 1);

pthread_t readThread_t, sendThread_t;  /* thread variables */

pthread_create(&readThread_t, NULL, (void *)readThread, (void *)&fd);
pthread_create(&sendThread_t, NULL, (void *)sendThread, (void *)&fd);

pthread_join(readThread_t, NULL);
pthread_join(sendThread_t, NULL);

close(fd);

return 0;
}/*main*/


 the code would send "hello" string to the uart (Universal Asynchronous Receiver/Transmitter) per 500 milli-second, and print data which have been received.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux rs232