串口读取数据部分数据有错误

需求 在使用串口调试助手调试读写程序时,发现在开启定时 10ms 发送的情况下,接收到的数据有时候会不对。 解决 原因 经过反复调试,最终确定问题是 RS485 导致的问题。因为下面几个原因叠加导致: RS485 是半双工设备,同时只能收或者发。 串口调试助手,定时发送没有办法刚好完全避开程序的发送 所以,就出现了,当程序在发送时,串口调试助手也在发送,等到程序接收的时候,数据就不完整,或者有问题。 验证 验证也很简单: 程序只收不发,然后查看所有受到的数据,没有错误。 程序发送的间隔拉的很长,观察在发送间隔中的接收数据,也是没有错误的。 参考

<span title='2023-03-21 13:46:00 +0800 CST'>2023-03-21</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;18 words&nbsp;·&nbsp;RamLife

Linux 键盘输入读取

需求 读取二维码 DataMatrix 格式的扫码头是 usb 接口,通过键盘输入的形式输出数据。程序需要读取这些数据。 解决 设备信息 获取设备信息 键盘输入在 linux 当中属于 input 子系统,对应的设备号是 /dev/input/eventX, 如果希望知道自己的设备具体对应那个,可以使用下面这条命令来获取所有的输入设备信息。如果希望了解输入的更多内容,可以查看 https://www.kernel.org/doc/Documentation/input/input.txt cat /proc/bus/input/devices I: Bus=0019 Vendor=2454 Product=6575 Version=0010 N: Name="mtk-kpd" P: Phys= S: Sysfs=/devices/platform/mtk-kpd/input/input0 U: Uniq= H: Handlers=event0 B: PROP=0 B: EV=3 B: KEY=1c0000 0 0 0 I: Bus=0019 Vendor=0000 Product=0000 Version=0000 N: Name="ACCDET" P: Phys= S: Sysfs=/devices/virtual/input/input1 U: Uniq= H: Handlers=event1 B: PROP=0 B: EV=3 B: KEY=80 0 78 0 40c0000 0 0 0 I: Bus=0000 Vendor=0000 Product=0000 Version=0000 N: Name="hwmdata" P: Phys= S: Sysfs=/devices/virtual/input/input2 U: Uniq= H: Handlers=event2 B: PROP=0 B: EV=5 B: REL=2 分析设备信息 根据上面的输出信息,可以根据 Name 这一行大概找到自己的设备,如果希望知道设备支持的详细内容可以查看 EV 值,根据 /usr/include/linux/input-event-codes....

<span title='2023-03-14 11:46:00 +0800 CST'>2023-03-14</span>&nbsp;·&nbsp;8 min&nbsp;·&nbsp;1570 words&nbsp;·&nbsp;RamLife

多进程如何使用单串口的方案

需求 数据处理的程序是多进程的,那么如何让多进程的处理程序使用硬件上的单个的串口呢? 解决 最适合的方法还是,把串口部分的程序独立出来,做成一个服务程序。 这个服务,对下是一条一条的把数据帧通过硬件串口进行收发。 这个服务,自身需要对数据进行一定的加工处理,比如按照指定的协议对数据帧进行编解码。 这个服务,对上可以使用队列,管道等进程间通讯的方式,把相关数据送到不同的进程中去。 当然如果多进程的处理功能特别简单,也可以考虑把这个处理的功能和串口二合一,然后通过多线程的方式去做。 参考 这个很有必要讨论讨论,我搞过一小段时间售货机,串口通信 多个进程间如何实现串口控制共享 linux两个进程同时打开串口,linux串口操作及设置详解

<span title='2023-03-13 15:01:00 +0800 CST'>2023-03-13</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;12 words&nbsp;·&nbsp;RamLife

crosses initialization of XXX

需求 今天修改了几行程序后,编译不通过,报错为 crosses initialization of. 解决 经过搜索和尝试,发现是 goto 语句引起的,但是也不单纯是 goto 引起的。主要是同时达到了下面两个条件。 变量定义并没有都放在函数的开始。 使用 goto 的语句下面,还有新定义的变量。 所以,编译器担心 goto 跳过这些新定义的变量可能导致程序执行的结果有问题,就报错了。解决也很简单,把使用 goto 语句下面新定义的变量移动到上面就可以了。 参考 goto语句引起的crosses initialization of XXX

<span title='2023-03-13 14:36:00 +0800 CST'>2023-03-13</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;25 words&nbsp;·&nbsp;RamLife

Linux 串口的配置和读写

需求 需要在 linux 中配置好串口,并且通过串口收发数据 解决 打开串口 打开串口直接使用 open 函数即可,需要注意的是, flag 中的参数 O_NOCTTY, O_NDELAY. O_NOCTTY:告诉Unix这个程序不想成为“控制终端”控制的程序,不说明这个标志的话,任何输入都会影响你的程序。 O_NDELAY:告诉Unix这个程序不关心DCD信号线状态,即其他端口是否运行,不说明这个标志的话,该程序就会在DCD信号线为低电平时停止。但是在 man 中,是把 O_NDELAY 和 O_NONBLOCK 放在一起,并没有说明两者的区别,所以这这个参数的作用存疑。 open 时需要指定串口的串口号,比如 /dev/ttyS0 int OpenDevice(const char * dev) { int fd = 0; fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { fprintf(stderr, "Can not open serial port %s", dev); return -1; } cout << "open " << dev << " Ok!" << endl; return fd; } if ((serial_fd = OpenDevice(kSerialName....

<span title='2023-03-13 14:24:00 +0800 CST'>2023-03-13</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;782 words&nbsp;·&nbsp;RamLife

syslog 使用及宏

需求 syslog 虽然使用起来很方便,但是直接使用有几个问题: 虽然有日志信息,但是不够全面不方便定位 那么多的日志都混在一起,没有重点,调试时不方便 debug 和 release 时,日志应该不一样。 解决 日志信息更丰富 syslog 可以使用 __FILE__, __LINE__, __FUNCTION, 这几个来标识出当前的日志是在那个文件,第几行,哪个函数输出的。 syslog(LOG_DEBUG, "%s: %d: %s --> class construct", __FILE__, __LINE__, __FUNCTION__); 使用宏来开关日志 下面这个是普通替代的宏,可以用于开关日志. #ifdef xxx #define LOG(priority, format, ...) syslog(priority, format, ## __VA_ARGS__) #else #define LOG(priority, format, ...) #endif 使用宏来减少输入 但是每条日志都要这样写,就太麻烦了,我们可以使用宏来解决这个问题: #define LOG(priority, format, ...) syslog(priority, "%s: %d: %s --> "#format, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__) LOG(LOG_DEBUG, "class construct"); 上面这条宏,我们在使用时,不需要显式的写出相关的参数,宏展开的时候,会自动帮我们加上这些参数,日志会包含文件名,行号,函数名. 使用宏增加日志等级 当多条日志信息在一起的时候,比较难抓住重点,虽然可以使用搜索,但是终归没有那么方便。我们可以通过宏给日志消息里面附上对应的等级,也方便后期维护时使用脚本进行解析。 #define LOG(priority, format, ....

<span title='2023-03-06 15:02:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;223 words&nbsp;·&nbsp;RamLife

系统日志 syslog 相关函数使用

需求 需要让 linux 平台的软件能够输出日志,便于后期的调试和分析。 解决 linux 平台原生支持 syslog 类型的日志服务,不同的发行版可能不同,有可能是 syslog, syslog-ng, rsyslogd 等等。但是具体的程序中输出日志的函数其实是一样的,主要就是三个函数 openlog(), syslog(), closelog(). 调用 syslog 函数之前,首先需要包含相应的头文件 #include <syslog.h> openlog 函数原型为: void openlog(const char *ident, int option, int facility);, 作用是打开一个到系统日志记录程序的连接,实际使用时,这个函数可以省略,在调用 syslog() 时,如果没有打开,会自动打开一个。但是显式使用 openlog 可以进行更多的设定。 ident, 设置日志中的生成者的标识,正常使用 NULL 就可以了,会使用程序名进行标识。如果需要自定义一个标识,那么输入字符串即可。 option, 设置日志相关属性,简单的可以使用 openlog(NULL, LOG_CONS|LOG_PID, 0); 即可,复杂的使用 openlog(NULL, LOG_CONS | LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_LOCAL0);, 具体的含义可以 man openlog 可选配置 描述 LOG_CONS 直接写入系统控制台,如果有一个错误,同时发送到系统日志记录。 LOG_NDELAY 立即打开连接(通常,打开连接时记录的第一条消息)。 LOG_NOWAIT 不要等待子进程,因为其有可能在记录消息的时候就被创建了(GNU C库不创建子进程,所以该选项在Linux上没有影响。) LOG_ODELAY 延迟连接的打开直到syslog函数调用。(这是默认情况下,需要没被指定的情况下。) LOG_PERROR (不在SUSv3情况下)同时输出到stderr(标准错误文件)。 LOG_PID 包括每个消息的PID。 facility, 正常为 0 即可。 设置 描述 LOG_AUTH 认证系统:login、su、getty等 LOG_AUTHPRIV 同LOG_AUTH,但只登录到所选择的单个用户可读的文件中 LOG_CRON cron守护进程 LOG_DAEMON 其他系统守护进程,如routed LOG_FTP 文件传输协议:ftpd、tftpd LOG_KERN 内核产生的消息 LOG_LPR 系统打印机缓冲池:lpr、lpd LOG_MAIL 电子邮件系统 LOG_NEWS 网络新闻系统 LOG_SYSLOG 由syslogd(8)产生的内部消息 LOG_USER 随机用户进程产生的消息 LOG_UUCP UUCP子系统 LOG_LOCAL0~LOG_LOCAL7 为本地使用保留 syslog 函数原型为 void syslog(int priority, char*format,……);, 有需要输出的日志信息,就调用这个函数进行输出。...

<span title='2023-02-14 09:34:00 +0800 CST'>2023-02-14</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;142 words&nbsp;·&nbsp;RamLife