Recently, I am using the imx6sx serial port for debugging, using other serial ports, and writing an application program to read data, and use other upper computers to send. After the kernel is fully started, the application program is executed first and then the serial port host computer is used to send data, which can be obtained normally. But I first used the serial port host computer to send data and then started the board and opened the application program. I found that the data were all garbage values, and the number of bytes was also defined as the largest. After a while, the number of bytes became 0, and there was no data. It is normal after restarting the application several times.
#include <stdio.h> //标准输入输出,如printf、scanf以及文件操作
#include <stdlib.h> //标准库头文件,定义了五种类型、一些宏和通用工具函数
#include <unistd.h> //定义 read write close lseek 等Unix标准函数
#include <sys/types.h> //定义数据类型,如 ssiz e_t off_t 等
#include <sys/stat.h> //文件状态
#include <fcntl.h> //文件控制定义
#include <termios.h> //终端I/O
#include <errno.h> //与全局变量 errno 相关的定义
#include <getopt.h> //处理命令行参数
#include <string.h> //字符串操作
#include <time.h> //时间
#include <sys/select.h> //select函数
#include <signal.h>
int fd;
void close_fd(int sg_no)
{
if(SIGINT == sg_no) {
close(fd);
printf("close serialport file\r\n");
exit(0);
}
}
int setOpt(int fd, int nSpeed, int nBits, int nParity, int nStop)
{
struct termios newtio, oldtio;
// 保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息
if (tcgetattr(fd, &oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero(&newtio, sizeof(newtio)); //新termios参数清零
newtio.c_cflag |= CLOCAL | CREAD; //CLOCAL--忽略 modem 控制线,本地连线, 不具数据机控制功能, CREAD--使能接收标志
// 设置数据位数
newtio.c_cflag &= ~CSIZE; //清数据位标志
switch (nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size\n");
return -1;
}
// 设置校验位
switch (nParity)
{
case 'o':
case 'O': //奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E': //偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'n':
case 'N': //无校验
newtio.c_cflag &= ~PARENB;
break;
default:
fprintf(stderr, "Unsupported parity\n");
return -1;
}
// 设置停止位
switch (nStop)
{
case 1:
newtio.c_cflag &= ~CSTOPB;
break;
case 2:
newtio.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return -1;
}
// 设置波特率 2400/4800/9600/19200/38400/57600/115200/230400
switch (nSpeed)
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 230400:
cfsetispeed(&newtio, B230400);
cfsetospeed(&newtio, B230400);
break;
default:
printf("\tSorry, Unsupported baud rate, set default 9600!\n\n");
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
// 设置read读取最小字节数和超时时间
newtio.c_cc[VTIME] = 1; // 读取一个字符等待1*(1/10)s
newtio.c_cc[VMIN] = 1; // 读取字符的最少个数为1
tcflush(fd,TCIFLUSH); //清空缓冲区
if (tcsetattr(fd, TCSANOW, &newtio) != 0) //激活新设置
{
perror("SetupSerial 3");
return -1;
}
printf("Serial set done!\n");
return 0;
}
int uart_init(int fd)
{
struct termios newtio, oldtio;
//fcntl(fd, F_SETFL, 0);
if(tcgetattr(fd, &oldtio) !=0 ){
printf("tcgetattr error\r\n");
return -1;
}
bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~PARENB;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
// newtio.c_cflag &= ~HUPCL;
// newtio.c_iflag &= ~INPCK;
// newtio.c_iflag |= IGNBRK;
// newtio.c_iflag &= ~ICRNL;
// newtio.c_iflag &= ~IXON;
// newtio.c_lflag &= ~IEXTEN;
// newtio.c_lflag &= ~ECHOK;
// newtio.c_lflag &= ~ECHOCTL;
// newtio.c_lflag &= ~ECHOKE;
// newtio.c_oflag &= ~ONLCR;
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
sleep(1);
//tcflush(fd, TCIOFLUSH);
tcflush(fd,TCIOFLUSH);
if(tcsetattr(fd, TCSANOW, &newtio) != 0){
printf("com set error\r\n");
}
return 0;
}
int UART_Recv(int fd, char *rcv_buf, int data_len, int timeout)
{
int len, fs_sel;
fd_set fs_read;
struct timeval time;
time.tv_sec = timeout / 1000; //set the rcv wait time
time.tv_usec = timeout % 1000 * 1000; //100000us = 0.1s
FD_ZERO(&fs_read); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(fd, &fs_read); //添加描述符
// 超时等待读变化,>0:就绪描述字的正数目, -1:出错, 0 :超时
fs_sel = select(fd + 1, &fs_read, NULL, NULL, &time);
printf("fs_sel = %d\n", fs_sel);
if(fs_sel)
{
len = read(fd, rcv_buf, data_len);
return len;
}
else
{
// printf("Sorry,I am wrong!");
return -1;
}
}
int main(int argc, char *argv[])
{
char read_buf[100];
int read_size = 0;
int ret,i;
char tmp[50];
signal(SIGINT,close_fd);
fd = open("/dev/ttymxc3", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0) {
printf("can't open serialport\r\n");
return -1;
} else{
printf("open serialport success\r\n");
}
if (fcntl(fd, F_SETFL, 0) < 0) //阻塞,即使前面在open串口设备时设置的是非阻塞的
{
printf("fcntl failed!\n");
}
if (isatty(fd) == 0)
{
printf("standard input is not a terminal device\n");
close(fd);
return -1;
}
else
{
printf("is a tty success!\n");
}
printf("fd-open=%d\n", fd);
// uart_init(fd);
// 设置串口参数
if (setOpt(fd, 9600, 8, 'N', 1)== -1) //设置8位数据位、1位停止位、无校验
{
fprintf(stderr, "Set opt Error\n");
close(fd);
exit(1);
}
tcflush(fd, TCIOFLUSH); //清掉串口缓存
fcntl(fd, F_SETFL, 0); //串口阻塞
while(1)
{
// scanf("%s",tmp);
// ret = strcmp(tmp, "hello");
// if(!ret) {
// write_size = write(fd, write_buf, sizeof(write_buf));
// if(write_size < 0) {
// printf("write error\r\n");
// return -1;
// }
memset(read_buf, 0, sizeof(read_buf));
ret = UART_Recv(fd, read_buf, 100,10000);
printf("read len:%d\r\n",ret);
for(i = 0; i< ret; i++){
printf("%c",read_buf[i]);
}
printf("\r\n");
usleep(300000);
}
close(fd);
return 0;
}