sudo nano /boot/cmdline.txt
删除 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200
sudo nano /boot/config.txt
最后增加下面两句话:
dtoverlay=pi3-miniuart-bt
enable_uart=1
sudo apt-get install minicom
minicom -b 9600 -o -D /dev/ttyAMA0
-b 表示波特率 -D 表示端口号 -o 未知,也可以去掉
int uart_open(int fd,const char *pathname)
{
assert(pathname);
/*打开串口*/
fd = open(pathname,O_RDWR|O_NOCTTY|O_NDELAY|O_NONBLOCK);
if(fd == -1)
{
perror("Open UART failed!");
return -1;
}
/*设置串口非阻塞,因为这里是以非阻塞形式打开的,所以第三个参数为0*/
if(fcntl(fd,F_SETFL,0) < 0)
{
fprintf(stderr,"fcntl failed!\n");
return -1;
}
return fd;
}
// 115200,0,8,'N',1
int uart_set(int fd,int baude,int c_flow,int bits,char parity,int stop)
{
struct termios options;
/*获取串口当前的配置*/
if(tcgetattr(fd,&options) < 0)
{
perror("tcgetattr error");
return -1;
}
/*配置波特率*/
switch(baude)
{
case 4800:
cfsetispeed(&options,B4800);
cfsetospeed(&options,B4800);
break;
case 9600:
cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
case 19200:
cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
break;
case 38400:
cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
break;
case 115200:
cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
break;
case 230400:
cfsetispeed(&options,B230400);
cfsetospeed(&options,B230400);
break;
default:
fprintf(stderr,"Unkown baude!\n");
return -1;
}
/*设置控制模式*/
options.c_cflag |= CLOCAL;//保证程序不占用串口
options.c_cflag |= CREAD;//保证程序可以从串口中读取数据
/*设置数据流控制*/
switch(c_flow)
{
case 0://不进行流控制
options.c_cflag &= ~CRTSCTS;
break;
case 1://进行硬件流控制
options.c_cflag |= CRTSCTS;
break;
case 2://进行软件流控制
options.c_cflag |= IXON|IXOFF|IXANY;
break;
default:
fprintf(stderr,"Unkown c_flow!\n");
return -1;
}
/*设置数据位*/
switch(bits)
{
case 5:
options.c_cflag &= ~CSIZE;//屏蔽其他标志位
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag &= ~CSIZE;//屏蔽其他标志位
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag &= ~CSIZE;//屏蔽其他标志位
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag &= ~CSIZE;//屏蔽其他标志位
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unkown bits!\n");
return -1;
}
/*设置校验位*/
switch(parity)
{
/*无奇偶校验位*/
case 'n':
case 'N':
options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_iflag &= ~INPCK;//INPCK:使奇偶校验起作用
break;
/*设置为空格,即停止位为2位*/
case 's':
case 'S':
options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag &= ~CSTOPB;//CSTOPB:使奇偶校验起作用
break;
/*设置奇校验位*/
case 'o':
case 'O':
options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag |= PARODD;//PARODD:若设置则为奇校验,否则为偶校验
options.c_cflag |= INPCK;//INPCK:使机构校验起作用
options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节, 否则保留全部8位
break;
/*设置偶校验*/
case 'e':
case 'E':
options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag &= ~PARODD;//PARODD:若设置则为奇校验,否则为偶校验
options.c_cflag |= INPCK;//INPCK:使机构校验起作用
options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节, 否则保留全部8位
break;
default:
fprintf(stderr,"Unkown parity!\n");
return -1;
}
/*设置停止位*/
switch(stop)
{
case 1:
options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位
break;
case 2:
options.c_cflag |= CSTOPB;//CSTOPB:使用两位停止位
break;
default:
fprintf(stderr,"Unkown stop!\n");
return -1;
}
/*设置输出模式为原始输出*/
options.c_oflag &= ~OPOST;//OPOST:若设置则按定义的输出处理,否则所有c_oflag失效
/*设置本地模式为原始模式*/
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/*
*ICANON:允许规范模式进行输入处理
*ECHO:允许输入字体的本地回显
*ECHOE:在接收EPASE时执行Backspace,Space,Backspace组合
*ISIG:允许信号
*/
/*设置等待时间和最小接收字符*/
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 1;//最少读取一个字符
/*如果数据溢出,值接受数据,但是不进行读操作*/
tcflush(fd,TCIFLUSH);
options.c_iflag = 0;
options.c_oflag = 0;
options.c_lflag = 0;
/*配置激活*/
if(tcsetattr(fd,TCSANOW,&options) < 0)
{
perror("tcsetattr failed");
return -1;
}
return 0;
}
树莓派接收配置完成后,如果没有 options.c_iflag = 0; options.c_oflag = 0; options.c_lflag = 0;这三行代码,会导致数据接收不稳定
int uart_close(int fd)
{
assert(fd);
close(fd);
return 0;
}
使用linux接口函数read和write函数就可以实现串口的读写