#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
// rcp uart root@192.168.1.1:/usr/
#define BAUDRATE B115200
#define UART_DEVICE "/dev/ttyS1"
#define FALSE -1
#define TRUE 0
/**
*@brief 设置串口通信速率
*@param fd 类型 int 打开串口的文件句柄
*@param speed 类型 int 串口速度
*@return void
*/
const int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
const int name_arr[] = {115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt); //读取终端参数
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i]) {
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]); //设置输入波特率
cfsetospeed(&Opt, speed_arr[i]); //设置输出波特率
status = tcsetattr(fd, TCSANOW, &Opt); //设置终端参数
if (status != 0) {
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
/**
*@brief 设置串口数据位,停止位和效验位
*@param fd 类型 int 打开的串口文件句柄
*@param databits 类型 int 数据位 取值 为 7 或者8
*@param stopbits 类型 int 停止位 取值为 1 或者2
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
int set_parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr( fd,&options) != 0) {
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n"); return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
/* 设置停止位*/
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
//时间控制,原始模式有效
options.c_cc[VTIME] = 10*10; /* 设置超时10 seconds(单位1/10s 100ms)*/
options.c_cc[VMIN] = 0;
// options.c_cc[VMIN] = FRAME_MAXSIZE; //阻塞条件下有效
//如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,~ICANON设置串口为原始模式,设置方式如下:
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
options.c_oflag &= ~OPOST; /*Output*/
/* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
// int main(int argc, char *argv[])
void *uart_thread(void *arg)
{
int fd, c=0, res;
char buf[1024];
printf("uart Start...\n");
fd = open(UART_DEVICE, O_RDWR|O_NOCTTY/*|O_NDELAY*/);
if (fd < 0) {
perror(UART_DEVICE);
exit(1);
}
printf("uart Open...\n");
set_speed(fd,115200);
if (set_parity(fd,8,1,'N') == FALSE) {
printf("Set Parity Error\n");
exit (0);
}
printf("uart Reading...\n");
while(1) {
//读数据
res = read(fd, buf, 255);
if(res==0)
continue;
printf("read=%d\n", res);
buf[res]=0;
printf("%s", buf);
//写数据
res = write(fd, buf, strlen(buf));
printf("write=%d\n\n",strlen(buf));
//退出
if (buf[0] == '#') break;
}
printf("uart Close...\n");
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
int res;
pthread_t thread1;
res = pthread_create(&thread1, NULL, uart_thread, NULL);
if(res != 0) {
printf("create uart_thread thread fail\n");
exit(res);
}
while (1) {
sleep(100);
}
return 0;
}
数据包长的话,读取数据会被截取,可以如下处理,分多次读取,配合非阻塞模式,可以实现快速高效读取
pos=0;
do{
usleep(2000);
// printf("\tpos=%d\n", pos);
res = read(fd, buf+pos, 255);
pos += res;
// printf("\tsingle read=%d\n", res);
}while(res);
仅此记录