概述
1 串口本质上也是字符设备 !!!!!!!!!!!!串口是不支持热拔插的。如果强行热拔插,容易损坏串口芯片!!!!!!!!!!!!!!!!!!!!!
名词解释:流控 "软件”流控制 :帧头帧尾
“硬件”流控制:信号线
一。流程
个人建议只要能够读懂代码,根据实际需求进行验证和配置即可。
1打开串口,一般使用 open 函数,打开之后会返回句柄,这个句柄就可以提供给发送和接收函数使用。
2初始化串口,串口需要配置波特率,数据位,校验位等等一系列的参数,初始化的过程掌握了,发送和接收都比较容易实现。
3发送和接收数据,前面提到过串口是属于字符设备的,可以使用 read 函数和 write 函数实现。
4关闭,使用函数 close 即可关闭串口。
1打开串口
1.1确认设备节点 dev目录下,在 4412 开发板中,设备节点使用的是 ttySAC*系列(0-3)
1.2原理图上对应:先在底板上找到外设,在到核心板上找对应的引脚名称
1.3例程:打开串口设备节点
2初始化串口
2.1 open()读取句柄
2.2 struct termio 来自内核文件archarmincludeasm
成员 tcflag_t c_iflag:输入模式标志
成员 tcflag_t c_oflag:输出模式标志
成员 tcflag_t c_cflag:控制模式标志
成员 tcflag_t c_lflag:本地模式标志
成员 cc_t c_line:line discipline
成员 cc_t c_cc[NCC]:control characters
2.3 #include <termios.h>
#include <unistd.h> //配置串口通用头文件
int tcgetattr(int fd, struct termios *termios_p)//读取当前串口参数
参数 1:fd 是 open 返回的文件句柄。
参数 2:*termios_p 是前面介绍的结构体
执行成功返回 0,失败返回-1
int cfsetispeed(struct termios *termios_p, speed_t speed);//修改输入波特率
int cfsetospeed(struct termios *termios_p, speed_t speed);修改输出波特率
参数 1:*termios_p 是前面介绍的结构体。
参数 2:speed 波特率,常用的 B2400,B4800,B9600,B115200,B460800 等等。
执行成功返回 0,失败返回-1
speed_t cfgetispeed(const struct termios *termios_p)//读取当前串口输入的波特率
speed_t cfgetospeed(const struct termios *termios_p)//读取当前输出的波特率
int tcflush(int fd, int queue_selector);用于清空串口中没有完成的输入或者输出数据。在接收或者发送数据的时候,
串口寄存器会缓存数据,这个函数用于清除这些数据
参数 1:fd 是 open 返回的文件句柄。
参数 2:控制 tcflush 的操作。
TCIFLUSH 清除正收到的数据,且不会读取出来;
TCOFLUSH 清除正写入的数据,且不会发送至终端;
TCIOFLUSH 清除所有正在发生的 I/O 数据。
执行成功返回 0,失败返回-1
int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);设置参数
参数 1:fd 是 open 返回的文件句柄。
参数 2:optional_actions 是参数生效的时间。
TCSANOW:不等数据传输完毕就立即改变属性;
TCSADRAIN:等待所有数据传输结束才改变属性;
TCSAFLUSH:清空输入输出缓冲区才改变属性
参数 3:*termios_p 在旧的参数基础上修改的后的参数
执行成功返回 0,失败返回-1
2.4代码
A 函数不懂用man命令查,里面有详细的参数介绍
B 关于阻塞与非阻塞要讨论(已解决)
C uartinit01.c ----pds
D 总是读不出数,可能是open函数的选项选错了(不是这个原因,但是参数要好好看)
这仅仅是应用程序,不是驱动程序,驱动程序是直接调用4412开发板写好的串口驱动,今后有时间去看一下
#include<stdio.h> //标准输出头文件
#include<sys/types.h> //文件操作头文件1
#include<sys/stat.h> //文件操作头文件2
#include<fcntl.h> //文件操作头文件3
#include<unistd.h> //文件操作头文件4
#include<string.h> //strlen()函数需要
#include<termios.h> //串口头文件
#include<error.h> //Linux定义错误的头文件
int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop);
void main()
{
int fd,w,i;
char *uart3 ="/dev/ttySAC3";//需要改动
char *buffer= "please input";
char buffer1[100];
memset(buffer1,0,sizeof(buffer1));
if((fd = open(uart3,O_RDWR|O_CREAT,0777))<0)
{
printf("open %s failed!n",uart3);
}else
{
printf("open %s success!!n",uart3);
set_opt(fd,115200,8,'N',1);
w = write(fd,buffer,strlen(buffer));
while(1)
{
if ((i= read(fd,buffer1,100))>0);
{
w = write(fd,buffer1,strlen(buffer1));
memset(buffer1,0,sizeof(buffer1));
i=0;
}
}
}
close(fd);
}
int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
struct termios newtio,oldtio;
if(tcgetattr(fd,&oldtio) !=0){
perror("SetupSerial 1");
return -1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch(nBits)
{ case 7 :
newtio.c_cflag |= CS7;
break;
case 8 :
newtio.c_cflag |= CS8;
break;
}
switch(nEvent)
{ case 'O' :
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E' :
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N' :
newtio.c_cflag &= ~PARENB;
break;
}
switch(nSpeed)
{
case 2400 :
cfsetispeed(&newtio,B2400);
cfsetispeed(&newtio,B2400);
break;
case 4800 :
cfsetispeed(&newtio,B4800);
cfsetispeed(&newtio,B4800);
break;
case 9600 :
cfsetispeed(&newtio,B9600);
cfsetispeed(&newtio,B9600);
break;
case 115200 :
cfsetispeed(&newtio,B115200);
cfsetispeed(&newtio,B115200);
break;
default :
cfsetispeed(&newtio,B9600);
cfsetispeed(&newtio,B9600);
break;
}
if(nStop == 1)
{
newtio.c_cflag &=~ CSTOPB;
}
else if(nStop == 2)
{
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VTIME] =0;
newtio.c_cc[VMIN] =0;
}
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!= 0)
{
perror("com set error");
return -1;
}
return 0;
}
最后
以上就是粗犷百褶裙为你收集整理的Linux 串口驱动的全部内容,希望文章能够帮你解决Linux 串口驱动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复