Linux下串口的使用
一般我们使用串口有两种方式,一是自己编写驱动程序通过操作寄存器的方式,然后编译进Linux中供应用层调用,二是直接使用Linux提供的设备系统来进行编程,绝大多数的人都采取第二种方式,,他是基于TTY的驱动程序框架来进行编程
串口对应的API
在Linux系统中,操作设备的统一接口就是:open/ioctl/read/write。
对于UART,又在ioctl之上封装了很多函数,主要是用来设置行规程。
所以对于UART,编程的套路就是:
open
设置行规程,比如波特率、数据位、停止位、检验位、RAW模式、一有数据就返回
read/write
1.引脚号的设置
比如我们要设置第30号的gpio引脚,可以使用下面几条语句来配置gpio的引脚模式和方向
echo 30 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio30/direction//输出方向
echo 0 > /sys/class/gpio/gpio30/value//设置为低电平
2.打开串口
这里我们需要注意的是打开串口的设备文件在/dev/ttyySACX,X值得是你得串口,比如你想使用串口一那么就打开/dev/ttyySAC1,然后对他进行读写得操作。
/**
功能:打开串口函数
参数fd:文件描述符
参数port:串口路径
返回值:成功 串口文件描述符
失败 -1
*/
int uart_open(int *fd, char* port)
{
*fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == *fd)
{
perror("Can't Open Serial Port");
return -1;
}
/*将串口恢复成阻塞,打开的时候是非阻塞的*/
/* if(fcntl(*fd, F_SETFL, 0) < 0)
{
printf("fcntl failed!\n");
return -1;
}
*/
/*测试是否为终端设备*/
if(0 == isatty(STDIN_FILENO))
{
printf("standard input is not a terminal device\n");
return -1;
}
return *fd;
}
3.串口的设置
/**
功能:串口常规配置接口uart
参数fd:串口文件描述符
参数speed:串口波特率{115200, 19200, 9600, 4800, 2400, 1200, 300};
参数flow_ctrl:流控 0:不启用流控 1:硬件流控 2:软件流控
参数databits:串口传输数据位 5,6,7,8
参数stopbits:串口传输数据停止位 1:一位停止位 2:两位停止位
参数parity:串口传输数据校验位 n:不使用奇偶校验 o:奇校验 e:偶校验
返回值:成功 0
失败 -1
*/
int uart_set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)
{
int i = 0;
int speed_arr[] = { B38400, B115200, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = { 38400, 115200, 19200, 9600, 4800, 2400, 1200, 300};
struct termios options;
memset(&options, 0, sizeof(options));
/*保留旧的串口配置,在原有的基础上更新配置*/
if(tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return -1;
}
/*关闭不必要的配置,配置成原始模式,关闭软件流控*/
options.c_iflag &= ~(IGNBRK | BRKINT | INLCR | ICRNL| IUCLC | INPCK | ISTRIP | IXON | IXANY | IXOFF);
options.c_iflag &= ~(ICRNL | IXON);//接收\r\n
options.c_oflag &= ~(OPOST | OLCUC | ONLCR | OCRNL);
options.c_cflag &= ~(CSIZE | PARENB | HUPCL);
options.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | ECHOE | ECHOK | ECHOCTL | ECHOKE|ISIG);
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 1;
options.c_cflag |= CLOCAL | CREAD;
/*波特率*/
for (i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
}
}
/*流控*/
switch(flow_ctrl)
{
case 0 :
options.c_cflag &= ~CRTSCTS;
break;
case 1 :
options.c_cflag |= CRTSCTS;
break;
case 2 :
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
/*数据位*/
switch (databits)
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
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,"Unsupported data size\n");
return -1;
}
/*停止位*/
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB; break;
case 2:
options.c_cflag |= CSTOPB; break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return -1;
}
/*校验位*/
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return -1;
}
/*刷新串口输入输出缓冲区*/
tcflush(fd,TCIOFLUSH);
/*配置新的串口*/
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("com set error!\n");
return -1;
}
return 0;
}
4.向串口发送一个字符
/**
功能:向串口发送一个字符
参数ch:待发送的字符
返回值:成功写入返回 0x00
失败写入返回 0x01
*/
unsigned char uart_putchar(unsigned char ch)
{
unsigned char status = 0;
status = write(uart_fd, &ch, 1);
if(status > 0)
return UART_PUT_SUCCESS;
else
return UART_PUT_FAIL;
}
5.向串口接收一个字符
/**
功能:向串口接收一个字符
参数ch:待接收的字符
参数wait_usec:等待n微秒
返回值:成功读入返回 0x02
失败读入返回 0x03
*/
unsigned char uart_getchar(unsigned char *ch, unsigned int wait_usec)
{
struct timeval tv;
fd_set set;
FD_ZERO(&set);
FD_SET(uart_fd, &set);
memset(&tv, 0, sizeof(tv));
tv.tv_sec = 0;
tv.tv_usec = wait_usec;
if(select(uart_fd+1, &set, NULL, NULL, &tv)>0)
{
if(FD_ISSET(uart_fd, &set))
{
read(uart_fd, ch, 1);
return UART_GET_SUCCESS;
}
}
return UART_GET_FAIL;
}
6.关闭串口
/**
功能:关闭串口
参数:无
返回值:无
*/
void uart_close(void)
{
printf("doing close !\n");
close(uart_fd);
}
版权声明:本文为CSDN博主「魔动山霸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_46217142/article/details/121321215
暂无评论