设为首页 加入收藏

TOP

Linux的串口非标准波特率设置更改(一)
2023-07-23 13:43:27 】 浏览:87
Tags:Linux

用的是全志的R528 SDK,Linux内核是5.4,新增加一个250000的非标准波特率

参考网络大神文档,实践并记录宝贵的经验。

方法:

1、修改内核的/include/uapi/asm-generic/termbits.h文件

这个CBAUD原来是0010017改为0030017,是用来做掩码计算的。

 

  图1

这两个是新加的

 

 

  图2

 这个头文件一共更改这三个地方。先说为什么增加波特率使用0020001而不在B4000000后面递增使用0010020,这是因为这个低位的20已经被占用了,

如下图3,所以找了没被占用的位置,0020000的中2这个bit位置在c_cflag中没被占用(c_cflag是用于设置波特率和其他一些信息的)。

第一处的0030017也是这个原因,就是将波特率使用的这些宏定义包含进去。

 

  图3

2、/drivers/tty/tty_baudrate.c文件

这个文件就是获取波特率具体数值的文件,应用端的数据传入到内核,内核解析并获得250k波特率这个数值就是在这个文件,

先在文件

头部的波特率列表中增加所需数值,如图4,其中的250000和B250000为新增加。

 

  图4

 修改函数speed_t tty_termios_baud_rate(struct ktermios *termios),图5

 

   图5

其中圈起来的地方是新加的,这就是根据刚才新加的部分进行波特率修改,新的0020001,与CBAUDEX2进行运算判断高位位置,

之所以cbaud+=30是因为前面已经有了30个波特率了,见图5。这样内核就修改完了。

最后重新编译内核, 重新烧录系统镜像。

 

3、应用程序测试验证

应用端的配置,应用端通常使用tcsetattr这个函数进行配置,在使能之前,对齐c_cflag进行赋值就可

struct termios , termios_new;

termios_new.c_cflag |= 0020001;

(其余配置省略)

tcsetattr(fdcom, TCSANOW, &termios_new);

这里说一下为什么不能使用cfsetispeed、cfsetospeed 函数。

因为这两个函数只能指定原来标准的波特率,设置我们非标准的0020001的时候就会设置失败

       //ret = cfsetispeed(&newttys1, 0020001); //printf("reti = %d\n",ret); //ret = cfsetospeed(&newttys1, 0020001); //printf("reto = %d\n",ret);

 

应用层测试代码

baud_test.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "uart_oper.h"


#define UART1_DEV_NAME  "/dev/ttyS1"  /*需根据实际端口修改*/
#define BUF_LEN 100


int main(int argc,char const * argv[]) { int fd =-1,ret =-1; char buff[BUF_LEN]={0}; int i =0; int n =0; int len = BUF_LEN; int baud = 0; if(argc !=2) { printf("arg is not 2\n"); return -1; } baud = atoi(argv[1]); printf("baud =%d\n",baud); fd = open(UART1_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY); if(fd < 0) { perror("Can't open uart1 port"); return(void *)"uart1 dev error"; } ret = set_serial(fd,baud, 8, 'N', 1); /*可能需要根据情况调整*/
// ret = set_serial(fd, 115200, 8, 'N', 1); /*可能需要根据情况调整*/
    if(ret < 0) { printf("set_serial error\n"); return -1; } for(i =0 ;i<100;i++) { buff[i] =0x55; } while(1) { n = write(fd, buff, len); printf("n =%d\n",n); if(n < 0) { printf("send write error\n"); sleep(1); return -1; } sleep(1); } return 0; } uart_oper.c #include <stdio.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include "uart_oper.h"

/** *@brief 配置串口 *@param fd:串口文件描述符. nSpeed:波特率, nBits:数据位 7 or 8, nEvent:奇偶校验位, nStop:停止位 *@return 失败返回-1;成功返回0; */

int set_serial(int fd, int nSpeed, int nBits, char nEvent, int nStop) { struct termios newttys1, oldttys1; /*保存原有串口配置*/
    if(tcgetattr(fd, &oldttys1) != 0) { perror("Setupserial 1"); return - 1; } memset(&newttys1, 0, sizeof(newttys1)); /*CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/ newttys1.c_cflag |= (CLOCAL | CREAD); newttys1.c_cflag &=~CSIZE; /*设置数据位*/
    switch(nBits)    /*数据位选择*/ { case 7: newttys1.c_cflag |= CS7; break; case 8: newttys1.c_cflag |= CS8; break; default:break; }
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇主题 2 Shell工具和脚本 下一篇【神医华佗】Ubuntu空间爆满?cup..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目