最近在测试一个开发板的串口是否可以正常使用,开发板使用了linux系统,因此就写了个串口的收发程序来测试。
1.首先使用open函数打开串口,在linux中一切设备都被当做文件来看待,测试的串口所对应的文件为 /dev/ttySAC。
fd = open("/dev/ttySAC2",O_RDWR|O_NOCTTY);
得到了一个文件描述符fd。
2.然后就是对这个串口进行设置,设置其波特率、数据位、校验位、停止位。
tcgetattr(fd,&opt);
cfsetispeed(&opt,B115200);
cfsetospeed(&opt,B115200);
opt.c_cflag |= (CLOCAL | CREAD);
// 无校验 8位数据位1位停止位
opt.c_cflag &= ~PARENB;
opt.c_cflag &= ~CSTOPB;
opt.c_cflag &= ~CSIZE;
// 8个数据位
opt.c_cflag |= CS8;
// 原始数据输入
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
opt.c_oflag &= ~(OPOST);
// 设置等待时间和最小接收字符数
opt.c_cc[VTIME] = 0;
opt.c_cc[VMIN] = 0;
// 处理未接收的字符
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&opt);
其中opt的类型为
struct termios {
tcflag_t c_iflag; /* 输入参数 */
tcflag_t c_oflag; /* 输出参数 */
tcflag_t c_cflag; /* 控制参数*/
tcflag_t c_ispeed; /* 输入波特率 */
tcflag_t c_ospeed; /* 输出波特率 */
cc_t c_line; /* 线控制 */
cc_t c_cc[NCCS]; /* 控制字符*/
};
个人感觉比较重要的是对于
opt.c_cc[VTIME] = 0;
opt.c_cc[VMIN] = 0; 的设置
MIN指定了一个read返回前的最小字节数,TIME指定等待数据到达的分秒数。
共有下面四种情形:
A.MIN>0,TIME>0
注意:这个时候的TIME为字节间定时,只在第一个字节被接收时启动。在该定时器超时之前,若已接收到MIN个字节,则read返回MIN个字节。如果在接收到MIN个字节之前,定时器已经超时,则read返回MIN个字节。如果在接到MIN个字节之前,该定时器已经超时,则read返回已经接收到的字节数,因为定时器实在接收到一个字节之后开始启动,所以最少会返回一个字节。如果一只收不到数据,那么read这个函数就会一直阻塞
B.MIN=0,TIME>0
TIME指定了一个调用read时的读定时器,当接收到一个字节时或者超时后才会返回。
C.MIN>0,TIME=0
在接收到MIN个字节之前永远不会返回,有可能永远阻塞在这里。
D.MIN=0,TIME=0
如果有数据的时候,read最多会返回所要求的字节数。如果无数据,则read会立即返回0.这种情况类似于recv的最后一个option为MSG_DONTWAIT时的情形。
在这里都设置为0,说明read执行之后,如果没有读到数据,会立即返回。
3.然后就是读取和接收串口数据了
while(1)
{
if(write(fd,wb,6)!=6)
printf("write error
");
retv=read(fd,buf,1024);
if(retv==-1)
printf("read failed
");
if(retv>0)
{
printf("receive data is %s
",buf);
}
usleep(10000);
}
首先向串口中写入数据,然后再从串口中读取数据,这时候只需要把这个串口的发送的引脚和接收的引脚相连,那么这个串口就能接收到自己发送的数据。并且休眠10ms。
完整程序如下:
#include /*标准输入输出定义*/
#include /*标准函数库定义*/
#include /*Unix 标准函数定义*/
#include
#include
#include /*文件控制定义*/
#include /*PPSIX 终端控制定义*/
#include /*错误号定义*/
#define FALSE -1
#define TRUE 0
int set_Parity(int fd,int databits,int stopbits,int parity);
int main()
{
char buf[1024];
char wb[6]="hello";
int fd,flag_close,retv;
struct termios opt;
fd = open("/dev/ttySAC2",O_RDWR|O_NOCTTY);
if(fd==-1)
{
printf("open failed
");
exit (0);
}
else
printf("open success
");
tcgetattr(fd,&opt);
cfsetispeed(&opt,B115200);
cfsetospeed(&opt,B115200);
opt.c_cflag |= (CLOCAL | CREAD);
// 无校验 8位数据位1位停止位
opt.c_cflag &= ~PARENB;
opt.c_cflag &= ~CSTOPB;
opt.c_cflag &= ~CSIZE;
// 8个数据位
opt.c_cflag |= CS8;
// 原始数据输入
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
opt.c_oflag &= ~(OPOST);
// 设置等待时间和最小接收字符数
opt.c_cc[VTIME] = 0;
opt.c_cc[VMIN] = 0;
// 处理未接收的字符
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&opt);
printf("start send
");
while(1)
{
if(write(fd,wb,6)!=6)
printf("write error
");
retv=read(fd,buf,1024);
if(retv==-1)
printf("read failed
");
if(retv>0)
{
printf("receive data is %s
",buf);
}
usleep(10000);
}
flag_close = close(fd);
if(flag_close == -1)
printf("Close the Device failed
");
return 0;
}