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

QT Text 相关 widget 追加文本不换行

需求 正常在 QTextEdit QTextBrowser 中使用 append 添加新内容,都是自动换行的,如果不希望自动换行怎么办? 解决 其实很简单,使用 insertPlainText 这个方法即可。 textBrowser->insertPlainText("hello "); textBrowser->insertPlainText("world"); insertPlainText接口是在当前光标插入文本(光标一般默认在末尾),不自动换行,所以会打印: hello world 参考 QTextEdit QTextBrowser追加文本不换行

<span title='2023-03-10 16:00:00 +0800 CST'>2023-03-10</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;20 words&nbsp;·&nbsp;RamLife

emacs cpp 使用 tags

需求 代码自动补全需要 tags. 解决 生成 tags tags 生成工具 使用 gtags 生成 tags, 如果没有 gtags=,需要安装 =global. sudo apt install global 生成 tags # dump index files to directory ~/obj if 3rd party library directory is read only cd /usr/include && MAKEOBJDIRPREFIX=~/obj gtags --objdir cd /usr/src/linux/include && MAKEOBJDIRPREFIX=~/obj gtags --objdir # # above two command lines are same as below two command lines # mkdir -p ~/obj/usr/include && cd /usr/include && gtags --objdir=~/obj/usr/include # mkdir -p ~/obj/usr/linux/include && cd /usr/linux/include && gtags --objdir=~/obj/usr/linux/include ....

<span title='2023-03-09 17:23:00 +0800 CST'>2023-03-09</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;157 words&nbsp;·&nbsp;RamLife

emacs tab 设置为4个空格

需求 默认的 emacs 换行是两个空格,需要改为4个空格,并且 tab 也是4个空格。 解决 只需要在 el 或者 org 配置文件中添加如下内容: ;; cc mode style, table instead of spaces (setq c-default-style "linux" c-basic-offset 4 tab-width 4 indent-tabs-mode t) 参考

<span title='2023-03-09 17:23:00 +0800 CST'>2023-03-09</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;30 words&nbsp;·&nbsp;RamLife

命令行调试串口

需求 在编程使用串口之前,希望先确定串口硬件和系统层面是否正常。 解决 可以使用 stty 来调试串口功能。 查询当前串口配置 sudo stty -aF /dev/ttyS0 上面这个命令可以打印出当前串口的所有配置,有些配置选项前面有 -, 这个表示关闭此选项,或者额外意义,具体可以参考手册 man stty. 需要注意这几个配置: speed, -parenb, cs8, -cstopb, -ixon, -ixoff, -echo. 表示: 波特率,关闭校验,8位,1位停止,无流控,无回显. 保存,读取当前配置 在进行串口配置之前,应该先保存现在配置,便于以后的恢复。 # 保存 sudo stty -gF /dev/ttyS0 > save_stty # 读取 sudo stty -F /dev/ttyS0 $(cat save_stty) 脚本中可以这样写: save_stty="$(stty -g)" ... stty $save_stty 配置串口 sudo stty -F /dev/ttyS0 speed 115200 cs8 -parenb -cstopb -ixon -echo 上面这条命令立即生效,即使已经使用 cat 读取串口数据。 读取数据 sudo cat /dev/ttyS0 *注意: *...

<span title='2023-03-09 11:55:00 +0800 CST'>2023-03-09</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;106 words&nbsp;·&nbsp;RamLife

gn 和 ninja 编译 hello world

需求 在 gn, ninja 的开发环境下,实现 hello world 的编译,用以摸清最简单用法。 解决 gn 文件准备 gn 相关的文件可以从 simple_build 这个例子里面复制,总共需要复制以下几个文件: .gn 这个文件是隐藏文件,很容易漏掉,并且是 gn 执行时最先寻找的文件。这个文件所在的位置就是项目源码的 root 位置。其中的内容就是简单的指定项目的构建 config 具体是那一个。例子中指定的是 build/BUILDCONFIG.gn. build/BUILDCONFIG.gn, build/BUILD.gn 这两个是针对项目的一些设置包括不同操作系统的设置。 build/toolchain/BUILD.gn 这个是针对工具链的一些设置。 BUILD.gn 这个才是我们一般进行配置的文件,主要是配置需要编译的文件,库,最终的可执行文件等等。注意,不能使用 tab, 只能使用 space. 编译 使用 gn 生成 ninja 编译脚本。下面这条命令会在 out 目录下生成 test 目录,并且生成的 ninja 脚本也放在这个文件夹里面。 gn gen out/test 使用 ninja 正式编译。生成的编译文件和最终文件都放在相应的文件夹里面。 ninja -C out/test/ 运行和查看 直接运行 out/test 目录下的 hello 就可以执行了。 可以使用 gn desc 来查看相关信息. gn desc out/test "//:hello" 参考 GN使用笔记...

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

ubuntu 20.04 安装 gn 和 ninja

需求 需要在 ubuntu 20.04 LTS 上面安装 gn + ninja 的构建环境,用于后续的开发。 解决 安装 ninja ninja 安装非常简单,ubuntu 源当中就有: sudo apt install ninja-build 安装 clang clang 用于 gn 的编译,ubuntu 源当中也有: sudo apt install clang 安装 gn gn 的安装有两种方法: 二进制文件: https://gn.googlesource.com/gn/+/refs/heads/main 这个网页上面可以找到 linux, win, mac 三个下载地址。 源码安装,本文主要介绍源码安装过程。 下载源码 官方源: https://gn.googlesource.com/gn Github: https://github.com/timniederhausen/gn Gitee: https://gitee.com/openharmony/third_party_gn 注意: 直接下载源码 python 那一步过不去,只有 git 拉下来的才可以。 这三个源,时效性是 官方 > github > gitee. 官方源是肯定需要科学才能拉下来的。 如果使用官方源: git clone https://gn.googlesource.com/gn 编译源码 编译前使用 python 检查,编译使用 clang....

<span title='2023-03-08 17:33:00 +0800 CST'>2023-03-08</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;159 words&nbsp;·&nbsp;RamLife

使用智能指针替代裸指针

需求 希望使用智能指针,能够尽量减少内存泄漏 解决 智能指针比较适合在局部变量领域,在生命周期结束时,会自动释放。 定义 std::unique_ptr<QSerialPort> port_ = nullptr; std::unique_ptr<int[]> buf_ = nullptr; std::shared_ptr<int> data_ = nullptr; std::weak_ptr<int> weak_ = nullptr; 赋值 port_ = make_unique<QSerialPort>(); // 未初始化 buf_ = make_unique<int[]>(new int[10]); // 初始化为 0 buf_ = make_unique<int[]>(new int[10]()); buf_ = make_unique<int[]>(new int[10]{}); // shared data_ = make_shared<int>(); // weak 必须绑定 shared weak_ = data_; 使用 -> 这个是调用指针指向的对象的相关操作 . 这个是智能指针自身的一些操作 直接使用 shared_ptr 指针有可能会产生循环引用的问题,导致死锁,无法释放。建议使用 weak_ptr 来配合 shared_ptr. 注意 weak_ptr 无法单独存在并使用。 weak_ptr 在使用的时候,需要通过 lock 来获取 shared_ptr 对象,如果相应的内存已经释放,那么会返回 nullptr, 可以通过这个判断内存是否有效。 weak_ptr 本身不会增加 shared_ptr 的引用次数。 释放 释放有好几种方法,最简单的就是第一种。...

<span title='2023-03-06 17:03:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;119 words&nbsp;·&nbsp;RamLife

调试信息宏 FILE LINE FUNCTION

需求 调试时,希望打印信息能够包含文件名,行号,函数名等 解决 编译器有提供相应的宏,可以如下使用,注意,行号是数值。 printf("error in %s %d %s\n", __FILE__, __LINE__, __FUNCTION__); 除了这些以外,还有其他的一些可用的宏,比如说: __DATE__ : 当前系统日期 Apr 19 2019 __TIME__ : 当前系统时间 例如 15:39:58 __TIMESTAMP__ : 当前时间日期 例如: printf(_TIMESTAMP_); 打印结果 Fri Apr 19 16:24:31 2019 参考 C/C++中的_FUNCTION_,__FILE__和__LINE__ 系统常用宏定义__TIME__ DATE __LINE__等 C/C++ 宏定义 FILE__、_LINE_、_func_、__TIME 等

<span title='2023-03-06 16:32:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;44 words&nbsp;·&nbsp;RamLife

连接字符串的宏

需求 需要宏来生成字符串,降低人工输入和防止出错 解决 可以使用 #, 让相应的参数作为字符串进行填充。 #define OUT(s) fprintf(stderr, "out: " #s "/n"); OUT(div == 0); // fprintf(stderr, "out: " "div == 0" "/n"); ## 可以用来连接多个参数,减少代码生成。用法简单: #define NAME(n) name##n int NAME(a); NAME(a) = 123; printf("%d\n", NAME(a)); 参考 C语言中如何使用宏连接多个字符串(#和##的用法) C++ 宏字符串拼接、宏参数拼接成符号、宏嵌套、宏变长参数 C语言宏定义##连接符和#符的使用

<span title='2023-03-06 16:26:00 +0800 CST'>2023-03-06</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;41 words&nbsp;·&nbsp;RamLife