Computer serial port data reading is often used when using sensors. Next, I introduce the method of reading Linux serial port data in a project. I hope it will be helpful to you.
A set of data transmitted by the sensor through serial port is 13 bytes. The data format is as follows:
We need to initialize the serial port before reading the serial port data. The initialization of the serial port needs three steps:opening the serial port, setting the parameters of the serial port (including baud rate, data bit, stop bit, check bit).
The procedure of opening serial port is as follow, function returns a handle:
int openPort()
{
int fd;
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY |O_NDELAY);
if(fd == -1)
{
perror("open serial failed!\n");
exit(1);
}
return fd;
}
SERIAL_PORT is a serial address;
O_RDWR means to open in a readable and writable manner;
O_NOCTTY indicates that if the open file is a terminal device, the terminal will not be regarded as a process control terminal;
O_NDELAY denotes opening a file in an uninterruptible manner.
Here is the program for setting baud rate and data bits
int setSpeed(int fd, int speed, struct termios Opt)
{
int i;
if(tcgetattr(STDIN_FILENO, &Opt) != 0)
{
perror("tcgetattr fd\n");
return 1;
}
//识别波特率,设置输入输出波特率
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]);
//设置数据接收方式
if(tcsetattr(fd, TCSANOW, &Opt) != 0)
{
perror("tcsetattr fd");
return 1;
}
tcflush(fd, TCIOFLUSH);
}
}
return 0;
}
int setParity(int fd, int databits, int stopbits, int parity, struct termios Opt)
{
if(tcgetattr(fd, &Opt) != 0)
{
perror("tcgetattr fd");
return 1;
}
Opt.c_cflag |= (CLOCAL | CREAD); //CLOCAL:忽略 modem 控制线。
//CREAD: 打开接受者。
switch(databits) //设置数据位数
{
case 7:
Opt.c_cflag &= ~CSIZE; //屏蔽字符大小位
Opt.c_cflag |= CS7; //选择7位数据位
break;
case 8:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size.\n");
return 1;
}
switch(parity) //设置校验位
{
case 'n':
Opt.c_cflag &= ~PARENB; //清除校验位
Opt.c_iflag &= ~INPCK; //启用输入奇偶检测。
break;
case 'o':
Opt.c_cflag |= PARENB; //使能校验位
Opt.c_cflag |= PARODD; //奇校验
Opt.c_iflag |= INPCK; //启用输入奇偶检测。
break;
case 'e':
Opt.c_cflag |= PARENB; //使能校验位
Opt.c_cflag &= ~PARODD; //偶校验
Opt.c_iflag |= INPCK; //启用输入奇偶检测。
break;
case 's':
Opt.c_cflag &= ~PARENB; //清除校验位
Opt.c_cflag &= ~CSTOPB; //设置一个停止位
Opt.c_iflag |= INPCK; //启用输入奇偶检测。
break;
default:
fprintf(stderr, "Unsupported parity.\n");
return 1;
}
switch(stopbits) //设置停止位
{
case 1:
Opt.c_cflag &= ~CSTOPB;
break;
case 2:
Opt.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "Unsupported stopbits.\n");
return 1;
}
Opt.c_cflag |= (CLOCAL | CREAD);
Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
Opt.c_oflag &= ~OPOST; //OPOST :启用具体实现自行定义的输出处理。
Opt.c_oflag &= ~(ONLCR | OCRNL); //OCRNL :将输出中的回车映射为新行符
//ONLCR :(XSI) 将输出中的新行符映射为回车-换行。
Opt.c_iflag &= ~(ICRNL | INLCR); //ICRNL :将输入中的回车翻译为新行 (除非设置了 IGNCR)(否则当输入信号有 CR 时不会终止输入)。
//INLCR :将输入中的 NL 翻译为 CR。(将收到的换行符号转换为Return)
Opt.c_iflag &= ~(IXON | IXOFF | IXANY); //IXON :启用输出的 XON/XOFF 流控制。
//IXOFF :启用输入的 XON/XOFF 流控制。
//IXANY :(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出。
tcflush(fd, TCIFLUSH); //清空输入缓存
//MIN = 0 , TIME =0; 有READ立即回传否则传回 0,不读取任何字元
Opt.c_cc[VTIME] = 0;
Opt.c_cc[VMIN] = 0;
if(tcsetattr(fd, TCSANOW, &Opt) != 0) //设置数据接收方式
{
perror("tcsetattr fd");
return 1;
}
return 0;
}
Use the following program to initialize the serial port, the function returns a handle.
int init(void)
{
int fd;
struct termios opt;
//打开串口
fd = openPort();
//设置波特率
if(setSpeed(fd, PORT_SPEED, opt) == 1)
{
printf("setSpeed failed!\n");
exit(1);
}
//设置数据位、停止位和校验位
if(setParity(fd, DATABITS, STOPBITS, PARITY, opt) == 1)
{
printf("setParity failed!\n");
exit(1);
}
if(tcsetattr(fd, TCSANOW, &opt) != 0) //TCSANOW:不等数据传输完毕就立即改变属性。
{ //TCSADRAIN:等待所有数据传输结束才改变属性。
perror("serial error");
return -1;
}
return fd;
}
A set of data has 13 characters, each time we read a character, we can judge whether it is the starting bit at each reading, and separate each group of data. The judgement method is as follows:
void readPort(int fd)
{
time_t t;
int signal=0,pm1_0,pm1_1,pm2_0,pm2_1,pm10_0,pm10_1,pm1,pm2,pm10,temporary;
int i,len,n,parameter1,parameter2,Initiator;
char read_buf[24],sql_insert[200];
while(1)
{
bzero(read_buf, sizeof(read_buf));
while((n = read(fd, read_buf, sizeof(read_buf))) > 0)
{
//printf("\nlen= %d \n",n);
for(i=0;i
I built MySQL database locally and wrote the readed datas directly into the database.
First, initialize the database using the following method:
int init_mysql() {
// init the database connection
g_conn = mysql_init(NULL);
/* connect the database */
if(!mysql_real_connect(g_conn, g_host_name, g_user_name, g_password, g_db_name, g_db_port, NULL, 0))
return -1;
return 0;
}
g_host_name is the database address;
g_user_name is the database user name;
g_password is the database password;
g_db_name is the name of the database;
g_db_port is the database port;
int executesql(const char * sql) {
/*query the database according the sql*/
if (mysql_real_query(g_conn, sql, strlen(sql)))
return -1;
return 0;
}