0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

“串口阻塞”你真的会用吗?

ZLG致远电子 2025-02-13 11:42 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

导读

在串口通信开发中,数据错乱是常见问题。本文将快速介绍串口标志位的作用及配置方法,帮助解决数据传输错误。

这是一个真实案例,用户反馈“串口向另外的设备发送数据,发现运行一段时间后,发送的消息会阻塞很久才会发出来,一下子出来很多数据”。经过帮客户检查应用程序源码,发现应用程序在串口阻塞方面没有做正确的处理,修改后解决。

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  非阻塞打开串口

open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NONBLOCK);

  • O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。
  • O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,也就是不关心端口另一端是否已经连接。如果不指定该标志,进程将一直在休眠状态,直到DCD信号线为0。简单点就是以非阻塞方式打开串口。

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  设置串口成阻塞方式可用fcntl设置串口的阻塞/非阻塞。1. 阻塞:fcntl(fd, F_SETFL, 0)fcntl中的F_SETFL只可以更改标志O_APPEND,O_NONBLOCK,O_SYNC 和 O_ASYNC;而0则表示清空这几个标志,其中O_NONBLOCK也没了,所以就变成了阻塞。2. 非阻塞:fcntl(fd, F_SETFL, O_NONBLOCK)检测打开的文件描述符是否连接到一个终端设备,进一步确认串口是否正确打开。

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  获取和设置termios1. 获取termios结构体(串口属性)

  • inttcgetattr(intfd,structtermios*termptr);
  • termptr:接收返回的termios,成功:0,失败:-1。

2. 保存先前的串口配置inttcsetattr(intfd,intopt,conststructtermios*termptr); 3. 设置串口属性3.1 opt:在串口驱动程序里有输入缓冲区和输出缓冲区。在改变串口属性时,缓冲区可能有数据存在,如何处理缓冲区中的数据,可通过opt 参数实现。

  • TCSANOW:更改立即发生;
  • TCSADRAIN:发送了所有输出后更改才发生,若更改输出参数则应用此选项;
  • TCSAFLUSH:发送了所有输出后更改才发生,在更改发生时未读的所有输入数据被删除(Flush)。

3.2 成功:0。3.2 失败:-1。

85db0ba6-e9bc-11ef-9434-92fbcf53809c.jpg  设置波特率1. 设置输入波特率

int cfsetispeed(struct termios *termptr, speed_t speed);

2.设置输出波特率

int cfsetospeed(struct termios *termptr, speed_t speed);

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  设置数据位(也称设置字符大小)通过 c_cflag 设置。

CSIZE //数据位屏蔽CS5//5个数据位CS6 //6个数据位CS7 //7个数据位CS8 //8个数据位

例如,设置串口的数据位为 8 位:

c_cflag &= ~CSIZE; //清除CSIZEc_cflag |= CS8; //设置CS8

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  设置奇偶校验位设置串口的奇偶校验是在 c_cflag 设置。

  • PARENB 进行奇偶校验。
  • PARODD 奇校验,否则为偶校验。

1. 无校验

c_cflag &= ~PARENB;

2.偶校验

c_cflag |= PARENB;c_cflag &= ~PARODD;

3. 奇校验

c_cflag |= PARENB;c_cflag |= ~PARODD;

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  设置停止位设置串口停止位是在 c_cflag 设置。1. 设置 1 位停止位

c_cflag &= ~CSTOPB; //清除CSTOPB标志位

2.设置 2 位停止位

c_cflag |= CSTOPB; //设置CSTOPB标志位

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  设置最少字符和等待时间c_cc[VTIME]和c_cc[VMIN]设置最少字符和等待时间,针对 read 而言。如果设置为0的话,则在任何情况下read()函数立即返回:

c_cc[VTIME] = 0;c_cc[VMIN] = 0;

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  清除串口缓冲由于串口在重新设置之后,需要对当前的串口设备进行适当的处理,通常使用tcflush实现。

int tcdrain(int fd); //使程序阻塞,直到输出缓冲区的数据全部发送完毕。int tcflow(int fd, int action); // 用于暂停或重新开始输出。int tcflush(int fd, int queue_selector); //用于清空输入/输出缓冲区。

使用tcflush()函数,对于在缓冲区中的尚未传输的数据,或者收到的,但是尚未读取的数据进行处理。queue_selector设置:

  • TCIFLUSH:对接收到而未被读取的数据进行清空处理。
  • TCOFLUSH:对尚未传送成功的输出数据进行清空处理。

TCIOFLUSH:即对尚未处理的输入输出数据进行清空处理。


85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  激活选项CLOCAL 和 CREAD 分别用于本地连接和接收使能。激活这两个选项:

c_cflag |= CLOCAL | CREAD;

85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  激活串口配置(属性)

在完成全部串口配置之后,要激活刚才的配置并使配置生效。使用属性设置函数 tcsetattr(),前面已有其说明。


85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  向串口写数据

直接调用wtrite()即可。


85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  从串口读数据调用read()读取串口数据,但在非规范模式/原始模式下需要设置VMIN和VTIME。

  • VMIN:非规范模式下读取的最小字符数。
  • VTIME:非规范模式下读数据时的延时,VTIME个1/10秒。

VMIN和VTIME组合有四种情况:

  • VMIN=0,VTIME=0:读取的最少字符数为0,延时时间为0,read立即返回。
  • VMIN>0,VTIME=0: read阻塞到读取VMIN个字符才返回。
  • VMIN=0,VTIME>0:有数据就返回,无数据等待VTIME个1/10秒返回。

VMIN>0,VTIME>0:读取VMIN个字符或前后两个字符的输入间隔超过VTIME个1/10秒后返回,因为在输入第一个字符之后系统才会启动定时器,所以在这种情况下,read至少读取一个字符。


85aca540-e9bc-11ef-9434-92fbcf53809c.jpg  串口操作顺序

  1. 保存原有串口属性(可选);
  2. 设置波特率;
  3. 设置激活选项,如c_cflag |= CLOCAL | CREAD;
  4. 设置数据位大小;
  5. 设置奇偶校验位;
  6. 设置停止位;
  7. 设置输出(可选),如c_oflag=0;0是清空标志;c_oflag&=~OPOST;
  8. 设置输入(可选);
  9. 设置c_lflag,如原始模式cfmakeraw(&termios);
  10. 设置读取特性,c_cc[VTIME]和c_cc[VMIN];
  11. 刷新缓冲区,tcflush();
  12. 设置串口属性,tcsetattr()。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5186

    文章

    20164

    浏览量

    329035
  • 串口
    +关注

    关注

    15

    文章

    1607

    浏览量

    81965
  • zlg
    zlg
    +关注

    关注

    1

    文章

    71

    浏览量

    39030
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    真的会用示波器吗?

    下面就以我见到的很多工程师常犯的问题予以纠正,分享一下我掌握的一些知识。
    发表于 01-19 10:34 5384次阅读
    <b class='flag-5'>你</b><b class='flag-5'>真的</b><b class='flag-5'>会用</b>示波器吗?

    Verilog语言中阻塞和非阻塞赋值的不同

    来源:《Verilog数字系统设计(夏宇闻)》 阻塞和非阻塞赋值的语言结构是Verilog 语言中最难理解概念之一。甚至有些很有经验的Verilog 设计工程师也不能完全正确地理解:何时使用非阻塞
    的头像 发表于 08-17 16:18 6968次阅读

    串口设备框架serial_v2源码分析-阻塞模式

    在serial_v2中,串口设备以应用层视角,即阻塞模式或非阻塞模式来作为该串口设备的开启标志.
    的头像 发表于 09-14 11:34 3244次阅读

    linux串口通信阻塞与非阻塞问题。

    一般情况下串口通信中read()函数都是阻塞的。当然也可以通过设置文件等方法把串口设为非阻塞的。这里就有一个问题,当串口设置为
    发表于 07-14 15:57

    关于串口读写阻塞,没有设置非阻塞标志,为什么还能继续打印

    我打开这个串口的时候没有设置非阻塞的标志,应该是默认阻塞的吧,但是上位机不向串口发送东西,也就是read没有读到东西的时候下面的printf还是会一直打印。我理解的
    发表于 03-15 16:51

    HIDDongle例子修改成串口出现阻塞

    想问个问题啊,我用HIDDongle那个例子修改,弄成串口的,为什么会有串口阻塞的问题出现呢
    发表于 03-31 09:11

    UART阻塞方式收发

    博主能力有限,有错误望大佬指出0x00 文章内容:UART阻塞方式收发UART中断方式收发UART中断回调函数UART DMA方式收发printf()函数串口重定向0x01 UART阻塞方式收发
    发表于 08-10 07:32

    解决串口传输“阻塞”问题的方案资料下载

    电子发烧友网为提供解决串口传输“阻塞”问题的方案资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
    发表于 04-20 08:45 2次下载
    解决<b class='flag-5'>串口</b>传输“<b class='flag-5'>阻塞</b>”问题的方案资料下载

    总结:这些Keil 软件仿真的串口调试技巧,都记熟了没有?资料下载

    电子发烧友网为提供总结:这些Keil 软件仿真的串口调试技巧,都记熟了没有?资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、
    发表于 04-21 08:48 11次下载
    总结:这些Keil 软件仿<b class='flag-5'>真的</b><b class='flag-5'>串口</b>调试技巧,<b class='flag-5'>你</b>都记熟了没有?资料下载

    时序逻辑中的阻塞和非阻塞

    Verilog HDL的赋值语句分为阻塞赋值和非阻塞赋值两种。阻塞赋值是指在当前赋值完成前阻塞其他类型的赋值任务,阻塞赋值由=来完成;非
    的头像 发表于 03-15 13:53 3631次阅读

    阻塞与非阻塞通信的区别 阻塞和非阻塞应用场景

    阻塞通信(Blocking Communication):当进行阻塞通信时,调用者在发起一个I/O操作后会被阻塞,直到该操作完成返回才能继续执行后续代码。
    的头像 发表于 06-15 17:32 7214次阅读

    什么是阻塞?怎么设计才能满足阻塞指标?

    阻塞就是外部有阻塞干扰信号的时候,设备还可以正常运行。一般分为带内阻塞和带外阻塞,由于直放站都是做宽带设备,一般只提带外阻塞
    的头像 发表于 10-10 11:22 3848次阅读

    HAL_UART_Transmit阻塞时会影响串口中断接收吗?

    最近项目里使用了两路串口透传数据,串口3中断接收数据,组包后通过串口1阻塞发送出去。
    的头像 发表于 10-26 14:24 2989次阅读
    HAL_UART_Transmit<b class='flag-5'>阻塞</b>时会影响<b class='flag-5'>串口</b>中断接收吗?

    作为射频工程师,真的会用“dB”?

    作为射频工程师,真的会用“dB”?
    的头像 发表于 12-06 14:51 1209次阅读
    作为射频工程师,<b class='flag-5'>你</b><b class='flag-5'>真的</b><b class='flag-5'>会用</b>“dB”?

    什么是阻塞和非阻塞

    什么是阻塞和非阻塞?我们就用管道的读写来举例子。
    的头像 发表于 03-25 10:04 1096次阅读