Linux应用层例程7 CAN 应用编程基础

2023-05-16

        CAN 是一种多主方式的串行通讯总线,基本设计规范要求有高的位速率,高抗电磁干扰性,而且能够检测出产生的任何错误。经过几十年的发展,现在,CAN 的高性能、高可靠性以及高实时性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。
        以汽车电子为例,汽车上有空调、车门、发动机、大量传感器等,这些部件、模块都是通过 CAN 总线连在一起形成一个网络,车载网络构想图如下所示:

CAN 的电气属性

        CAN 总线使用两根线来连接各个单元: CAN_H CAN_L CAN 控制器通过判断这两根线上的电位差来得到总线电平,CAN 总线电平分为显性电平和隐性电平两种。
1)显性电平表示逻辑“ 0 ”,此时 CAN_H 电平比 CAN_L 高,分别为 3.5V 1.5V ,电位差为 2V
2)隐形电平表示逻辑“ 1 ”,此时 CAN_H CAN_L 电压都为 2.5V 左右,电位差为 0V
CAN 总线就通过显性和隐形电平的变化来将具体的数据发送出去,如下图所示:

CAN 网络拓扑

        CAN 是一种分布式的控制总线,CAN 总线作为一种控制器局域网,和普通的以太网一样,它的网络由很多的 CAN 节点构成,其网络拓扑结构如下图所示

        CAN 网络的每个节点非常简单,均由一个 MCU (微控制器)、一个 CAN 控制器和一个 CAN 收发器构成,然后通过 CAN_H CAN_L 这两根线连接在一起形成一个 CAN 局域网络。 CAN 能够使用多种物理介质,例如双绞线、光纤等。最常用的就是双绞线。信号使用差分电压传送,两条信号线被称为“CAN_H ” 和“CAN_L ”,在我们的开发板上, CAN 接口使用了这两条信号线, CAN 接口也只有这两条信号线。
        由此可知,CAN 控制器局域网和普通的以太网一样,每一个 CAN 节点就相当于局域网络中的一台主机。
        途中所有的 CAN 节点单元都采用 CAN_H CAN_L 这两根线连接在一起, CAN_H CAN_H CAN_L 接 CAN_L CAN 总线两端要各接一个 120 Ω的端接电阻,用于匹配总线阻抗,吸收信号反射及回拨,提高数据通信的抗干扰能力以及可靠性。
        CAN 总线传输速度可达 1Mbps/S ,最新的 CAN-FD 最高速度可达 5Mbps/S ,甚至更高, CAN-FD 不在本章讨论范围,感兴趣的可以自行查阅相关资料。CAN 传输速度和总线距离有关,总线距离越短,传输速度越快。

CAN 总线通信模型  

        CAN 总线传输协议参考了 OSI 开放系统互连模型,也就是前面所介绍的 OSI 七层模型(具体详情参考29.2 小节)。虽然 CAN 传输协议参考了 OSI 七层模型,但是实际上 CAN 协议只定义了“传输层”、“数据链路层”以及“物理层”这三层,而应用层协议可以由 CAN 用户定义成适合特别工业领域的任何方案。已在工业控制和制造业领域得到广泛应用的标准是 DeviceNet,这是为 PLC 和智能传感器设计的。在汽车工业,许多制造商都有他们自己的应用层协议标准。

CAN 帧的种类

SocketCan 应用编程  

        由于 Linux 系统将 CAN 设备作为网络设备进行管理,因此在 CAN 总线应用开发方面, Linux 提供了 SocketCAN 应用编程接口,使得 CAN 总线通信近似于和以太网的通信,应用程序开发接口更加通用,也更加灵活。
        SocketCAN 中大部分的数据结构和函数在头文件 linux/can.h 中进行了定义,所以,在我们的应用程序 中一定要包含<linux/can.h> 头文件

操作一 创建 socket 套接字 、

CAN 总线套接字的创建采用标准的网络套接字操作来完成,网络套接字在头文件 <sys/socket.h> 中定义。 创建 CAN 套接字的方法如下:
int sockfd = - 1 ;
/* 创建套接字 */
sockfd = socket ( PF_CAN , SOCK_RAW , CAN_RAW );
if ( 0 > sockfd ) {
        perror ( "socket error" );
        exit ( EXIT_FAILURE );
}
        socket 函数在 30.2.1 小节中给大家详细介绍过,第一个参数用于指定通信域,在 SocketCan 中,通常将其设置为PF_CAN ,指定为 CAN 通信协议;第二个参数用于指定套接字的类型,通常将其设置为 SOCK_RAW ;第三个参数通常设置为 CAN_RAW

操作二 将套接字与 CAN 设备进行绑定

譬如,将创建的套接字与 can0 进行绑定,示例代码如下所示

......
struct ifreq ifr = {0};
struct sockaddr_can can_addr = {0};
int ret;
......
strcpy(ifr.ifr_name, "can0"); //指定名字
ioctl(sockfd, SIOCGIFINDEX, &ifr);
can_addr.can_family = AF_CAN; //填充数据
can_addr.can_ifindex = ifr.ifr_ifindex;
/* 将套接字与 can0 进行绑定 */
ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
if (0 > ret) {
 perror("bind error");
 close(sockfd);
 exit(EXIT_FAILURE);
}

操作三 设置过滤规则

        在我们的应用程序中,如果没有设置过滤规则,应用程序默认会接收所有 ID 的报文;如果我们的应用程序只需要接收某些特定 ID 的报文(亦或者不接受所有报文,只发送报文),则可以通过 setsockopt 函数设置过滤规则,譬如某应用程序只接收 ID 0x60A 0x60B 的报文帧,则可将其它不符合规则的帧全部给过滤掉,示例代码如下所示:
struct can_filter rfilter[2]; //定义一个 can_filter 结构体对象
// 填充过滤规则,只接收 ID 为(can_id & can_mask)的报文
rfilter[0].can_id = 0x60A;
rfilter[0].can_mask = 0x7FF;
rfilter[1].can_id = 0x60B;
rfilter[1].can_mask = 0x7FF;
// 调用 setsockopt 设置过滤规则
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
struct can_filter 结构体中只有两个成员, can_id can_mask
        如果应用程序不接收所有报文,在这种仅仅发送数据的应用中,可以在内核中省略接收队列,以此减少 CPU 资源的消耗。此时可将 setsockopt() 函数的第 4 个参数设置为 NULL ,将第 5 个参数设置为 0 ,如下所示:
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
操作四 数据发送/接收
        在数据收发的内容方面,CAN 总线与标准套接字通信稍有不同,每一次通信都采用 struct can_frame 结构体将数据封装成帧结构体定义如下:
struct can_frame {
 canid_t can_id; /* CAN 标识符 */
 __u8 can_dlc; /* 数据长度(最长为 8 个字节) */
 __u8 __pad; /* padding */
 __u8 __res0; /* reserved / padding */
 __u8 __res1; /* reserved / padding */
 __u8 data[8]; /* 数据 */
};
        can_id 为帧的标识符,如果是标准帧,就使用 can_id 的低 11 位;如果为扩展帧,就使用 0 28 位。 can_id 的第 29 30 31 位是帧的标志位,用来定义帧的类型,定义如下:
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* 扩展帧的标识 */
#define CAN_RTR_FLAG 0x40000000U /* 远程帧的标识 */
#define CAN_ERR_FLAG 0x20000000U /* 错误帧的标识,用于错误检查 */
/* mask */
#define CAN_SFF_MASK 0x000007FFU /* <can_id & CAN_SFF_MASK>获取标准帧 ID */
#define CAN_EFF_MASK 0x1FFFFFFFU /* <can_id & CAN_EFF_MASK>获取标准帧 ID */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
(1) 、数据发送
        对于数据发送,使用 write() 函数来实现,譬如要发送的数据帧包含了三个字节数据 0xA0 0xB0 以及 0xC0,帧 ID 123 ,可采用如下方法进行发送:
struct can_frame frame; //定义一个 can_frame 变量
int ret;
frame.can_id = 123;//如果为扩展帧,那么 frame.can_id = CAN_EFF_FLAG | 123;
frame.can_dlc = 3; //数据长度为 3
frame.data[0] = 0xA0; //数据内容为 0xA0
frame.data[1] = 0xB0; //数据内容为 0xB0
frame.data[2] = 0xC0; //数据内容为 0xC0
ret = write(sockfd, &frame, sizeof(frame)); //发送数据
if(sizeof(frame) != ret) //如果 ret 不等于帧长度,就说明发送失败
 perror("write error");
如果要发送远程帧 ( ID 123) ,可采用如下方法进行发送:
struct can_frame frame;
frame.can_id = CAN_RTR_FLAG | 123;
write(sockfd, &frame, sizeof(frame));
(2) 、数据接收
数据接收使用 read() 函数来实现,如下所示:
struct can_frame frame;
int ret = read(sockfd, &frame, sizeof(frame));
(3) 、错误处理
        当应用程序接收到一帧数据之后,可以通过判断 can_id 中的 CAN_ERR_FLAG 位来判断接收的帧是否为错误帧。如果为错误帧,可以通过 can_id 的其他符号位来判断错误的具体原因。错误帧的符号位在头文件<linux/can/error.h> 中定义。
 
/* error class (mask) in can_id */
#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
......
......

操作五 回环功能设置

        在默认情况下,CAN 的本地回环功能是开启的,可以使用下面的方法关闭或开启本地回环功能,在本地回环功能开启的情况下,所有的发送帧都会被回环到与 CAN 总线接口对应的套接字上。
int loopback = 0; //0 表示关闭,1 表示开启(默认)
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

CAN 应用编程实战

        本小节我们来编写简单地 CAN 应用程序。在 Linux 系统中, CAN 总线设备作为网络设备被系统进行统一管理。在控制台下,CAN 总线的配置和以太网的配置使用相同的命令。
        使用 ifconfig 命令查看 CAN 设备,如下所示:

 CAN 数据发送实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
int main(void)
{
 struct ifreq ifr = {0};
 struct sockaddr_can can_addr = {0};
 struct can_frame frame = {0};
 int sockfd = -1;
 int ret;

 /* 打开套接字 */
 sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
     if(0 > sockfd) {
     perror("socket error");
     exit(EXIT_FAILURE);
 }

 /* 指定 can0 设备 */
 strcpy(ifr.ifr_name, "can0");
 ioctl(sockfd, SIOCGIFINDEX, &ifr);
 can_addr.can_family = AF_CAN;
 can_addr.can_ifindex = ifr.ifr_ifindex;

 /* 将 can0 与套接字进行绑定 */
 ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
 if (0 > ret) {
 perror("bind error");
 close(sockfd);
 exit(EXIT_FAILURE);
}

 /* 设置过滤规则:不接受任何报文、仅发送数据 */
 setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

 /* 发送数据 */
 frame.data[0] = 0xA0;
 frame.data[1] = 0xB0;
 frame.data[2] = 0xC0;
 frame.data[3] = 0xD0;
 frame.data[4] = 0xE0;
 frame.data[5] = 0xF0;
 frame.can_dlc = 6; //一次发送 6 个字节数据
 frame.can_id = 0x123;//帧 ID 为 0x123,标准帧
 for ( ; ; ) {
 ret = write(sockfd, &frame, sizeof(frame)); //发送数据
 if(sizeof(frame) != ret) { //如果 ret 不等于帧长度,就说明发送失败
 perror("write error");
 goto out;
 }
 sleep(1); //一秒钟发送一次
 }
out:

 /* 关闭套接字 */
 close(sockfd);
 exit(EXIT_SUCCESS);
}
CAN 数据接收实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
int main(void)
{
 struct ifreq ifr = {0};
 struct sockaddr_can can_addr = {0};
 struct can_frame frame = {0};
 int sockfd = -1;
 int i;
 int ret;

 /* 打开套接字 */
 sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
 if(0 > sockfd) {
 perror("socket error");
 exit(EXIT_FAILURE);
 }

 /* 指定 can0 设备 */
 strcpy(ifr.ifr_name, "can0");
 ioctl(sockfd, SIOCGIFINDEX, &ifr);
 can_addr.can_family = AF_CAN;
 can_addr.can_ifindex = ifr.ifr_ifindex;

 /* 将 can0 与套接字进行绑定 */
 ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
 if (0 > ret) {
 perror("bind error");
 close(sockfd);
 exit(EXIT_FAILURE);
 }

 /* 设置过滤规则 */
 //setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

 /* 接收数据 */
 for ( ; ; ) {
 if (0 > read(sockfd, &frame, sizeof(struct can_frame))) {
 perror("read error");
break;
 }

 /* 校验是否接收到错误帧 */
 if (frame.can_id & CAN_ERR_FLAG) {
 printf("Error frame!\n");
 break;
 }

 /* 校验帧格式 */
 if (frame.can_id & CAN_EFF_FLAG) //扩展帧
 printf("扩展帧 <0x%08x> ", frame.can_id & CAN_EFF_MASK);
 else //标准帧
 printf("标准帧 <0x%03x> ", frame.can_id & CAN_SFF_MASK);

 /* 校验帧类型:数据帧还是远程帧 */
 if (frame.can_id & CAN_RTR_FLAG) {
 printf("remote request\n");
 continue;
 }

 /* 打印数据长度 */
 printf("[%d] ", frame.can_dlc);

 /* 打印数据 */
 for (i = 0; i < frame.can_dlc; i++)
 printf("%02x ", frame.data[i]);
 printf("\n");
 }

 /* 关闭套接字 */
 close(sockfd);
 exit(EXIT_SUCCESS);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux应用层例程7 CAN 应用编程基础 的相关文章

  • VScode使用时常见问题

    写在篇首 xff0c vscode各种蜜汁bug xff0c 记录一下解决方案供大家参考 1 无法使用C 43 43 万能头文件 include xff1c bits stdc 43 43 h xff1e 解决方案 在刷题的时候 xff0c
  • Socket网络编程总结

    网络中进程之间如何通信 Java最初是作为网络编程语言出现的 xff0c 其对网络提供了高度的支持 xff0c 使得客户端和服务器的沟通变成了现实 xff0c 而在网络编程中 xff0c 使用最多的就是Socket 像大家熟悉的QQ MSN
  • linux tcp并发式服务器应用SELECT函数编写实例源代码(转载)

    include lt stdio h gt include lt stdlib h gt include lt unistd h gt include lt errno h gt include lt string h gt include
  • Activity启动模式与任务栈(Task)、TaskAffinity应用场景【转】

    转载请注明出处 xff08 谢谢 xff09 xff1a Activity启动模式与任务栈 Task 全面深入记录 xff08 下 xff09 activities waiting to finish 任务栈 zejian 的博客 CSDN
  • VsCode技巧快捷键

    按住Alt 43 鼠标点击可以有多处光标同时编辑 快速显示大纲 相当于eclipse的打开当前类方法列表弹框 gt 设置为Alt 43 D 搜索go to symbol in File 设置即可 vscode设置匹配花括号跳转 Ctrl 4
  • jmeter察看结果树的响应数据时显示乱码

    找到jmeter的安装路径 xff08 即解压路径 xff09 打开apache jmeter 4 0 bin jmeter properties文件 搜索 encoding 关键字 xff0c 找到如下配置 xff1a The encod
  • class 和 struct的区别

    class 和 struct 最本质的区别 class 是引用类型 xff0c 它在堆中分配空间 xff0c 栈中保存的只是引用 xff1b 而 struct 是值类型 xff0c 它在栈中分配空间 什么是class class xff08
  • 第一周——总体了解STM32以及开发环境搭建

    什么是STM32 意法半导体 xff08 ST xff09 集团于1988年6月成立 xff0c 是由意大利的SGS微电子公司和法国Thomson半导体公司合并而成 STM32系列基于专为要求高性能 低成本 低功耗的嵌入式应用专门设计的AR
  • 【ros下激光雷达的简单使用】(1)

    雷达简单使用方法 xff1a 思蓝科技S2的激光雷达 查看硬件是否连接成功 xff1a 使用lsusb wpf 64 wpfpc lsusb Bus 002 Device 001 ID 1d6b 0003 Linux Foundation
  • AMD CPU 电脑突然画面声音突然卡顿,卡碟声,画面撕裂

    有时候会突然卡顿个一两秒 xff0c 然后自己好 xff0c 如果主板买的早 xff0c 没更新过BIOS版本 xff0c 可能是因为AMD的fTPM设置有个BUG xff0c 开启之后有概率会随机卡顿 xff0c 各大厂商最新的主板驱动应
  • STL —— vector,list,deque,使用与优缺点比较

    关于vector list deque 已经做过介绍 xff0c 本文是对三种容器的优劣做出比较 下面是vector list deque的博客链接 vector list deque vector list对比 底层结构 动态顺序表 xf
  • android手机版tcp或者udp通讯测试工具,可以用于工业设备或者系统开发时间测试tcp或是udp连接通讯是否正常工作

    TUtool 介绍 由于工作需要一款安卓的tcp udp测试工具 xff0c 而市场里没有或者不好用 xff0c 或者都是广告 xff0c 现在个人开发者又不让发布应用了 xff0c 小巧好用不收集用户信息的不收费没有广告的小工具只能自己用
  • microhard p900数传配置方法

    配置好的两个 xff08 多个 xff09 数传电台可以通过串口直接相互通讯 xff0c 两个 xff08 多个 xff09 数传之间无线连接 数传电台可以配置多种通讯方式 xff1a 点对点 点对多 mesh组网 xff08 电台数量 2
  • boost.asio异步调用使用智能指针

    boost asio中的异步async 函数需要传入回调函数参数 xff0c 如果回调函数使用lamda表达式 xff0c 在 capture 列表中传入智能指针 xff0c 智能指针会生效吗 xff1f 在async connect调用之
  • sscanf 格式化输入 的关键 VS2010\VC\crt\src\input.c

    VS2010 VC crt src ctype h define ischartype l Char Flag Locale Locale 61 NULL amp amp locale t Locale gt locinfo gt mb c
  • VS万能头文件添加方法(整理版)

    本文所使用的技术来自B站up主 昕辰丶 首先按照图中箭头找到VS在磁盘中的位置 按照箭头操作 先在搜索中输入msvc 然后点击Tools结尾的MSVC文件夹 点击这唯一的文件夹 打开include文件夹 新建一个文件夹并且命名为 bits
  • 集美大学-浙大版《C语言程序设计实验与习题指导(第3版)》

    这是我2020年大一入学前写的代码 xff0c 当时的测试点是全过的 xff0c 现在可能有些测试点过不去了 xff0c 如果有发现测试点过不去的 xff0c 可以联系我修改一下 xff0c 希望大家共同进步 xff08 工作量有点大 xf
  • 集美大学 - 2840 - 实验7-1 - 编程题

    实验7 1 1 一维数组 简化的插入排序 本题要求编写程序 xff0c 将一个给定的整数插到原本有序的整数序列中 xff0c 使结果序列仍然有序 输入格式 xff1a 输入在第一行先给出非负整数N xff08 lt 10 xff09 xff
  • 听劝,不要试图以编程为基础去学习网络安全

    目录 一 网络安全学习的误区1 不要试图以编程为基础去学习网络安全2 不要刚开始就深度学习网络安全3 收集适当的学习资料4 适当的报班学习 二 学习网络安全的些许准备1 硬件选择2 软件选择3 外语能力 三 网络安全学习路线第一阶段 xff
  • 集美大学 - 2840 - 实验8 - 编程题

    实验8 1 9 指针 输出学生成绩 本题要求编写程序 xff0c 根据输入学生的成绩 xff0c 统计并输出学生的平均成绩 最高成绩和最低成绩 建议使用动态内存分配来实现 输入格式 xff1a 输入第一行首先给出一个正整数N xff0c 表

随机推荐

  • vscode中文乱码问题及几种常见的解决方案

    问题及原因 问题原因 xff1a 代码文件的字符编码格式为UTF 8 xff0c 但是terminal的字符编码格式为GBK 解决思路 xff1a 统一代码文件和terminal的字符编码格式 解决办法 说明 xff1a 以下的解决方案是针
  • 集美大学 - 2840 - 实验11-2 - 函数题

    实验11 2 1 链表 建立学生信息链表 本题要求实现一个将输入的学生成绩组织成单向链表的简单函数 函数接口定义 xff1a span class token keyword void span span class token funct
  • python正则表达式

    python正则表达式 match函数 re match尝试从字符串的起始位置匹配一个模式 xff0c 如果不是起始位置匹配成功的话 xff0c match 就返回none 函数语法 xff1a re span class token pu
  • 轻松解决VS配置OpenCV环境及导出OpenCV的VS项目模板

    一 OpenCV配置 1 下载OpenCV 点击进入下载OpenCV的官网界面 这里以Windows为例 xff0c 其他同理 xff08 可直接下载最新 xff09 2 提取OpenCV 在这里浅说一句 xff0c 为了方便环境配置文件管
  • 最大子段和问题

    以下给出具体代码 xff1a span class token macro property span class token directive hash span span class token directive keyword i
  • 如何简单又好看地美化你的Ubuntu界面

    起因 最近使用Ubuntu界面实属是审美疲劳了 xff0c 使用老版本的一大问题就是 界面太难看了 秉持新手学习最好是用老一点的稳定版本的观念 Ubuntu旧版本使用或使用过的人非常非常多 xff0c 学习的过程中你一旦出现什么问题互联网上
  • 【实战】物联网安防监控项目【2】———boa服务器的移植

    一 boa服务器的移植 1 源码下载 1 1 boa简介 xff1a 其可执行代码只有大约60KB左右 xff0c Boa是一个单任务的HTTP服务器 xff0c Boa只能依次完成用户的请求 xff0c 而不会fork出新的进程来处理并发
  • 【实战】物联网安防监控项目【4】———从网页上控制A9的LED灯

    前言 学习了一个新知识 xff0c 当然要记录一下啦 这两天学习了boa服务器 cgic标准库和html标签语言 xff0c 又双叕解锁一个嵌入式的新玩法 cgic库是沟通C语言和html网页编程语言的一座桥梁 xff0c 通过在linux
  • 【实战】物联网安防监控项目【5】———把模拟数据传输到web网页、web显示mjpeg-streamer视频图像

    1 模拟数据传输到web 为了把硬件传感器上的数据上传到web网页 xff0c 我们需要在跑linux服务器的开发板上写一个应用程序 xff0c 并创建出几个线程来收集传感器检测到的数据 xff0c 通过进程 线程间通信 boa与cgic库
  • HttpGet Digest授权认证

    工具类 xff1a compile com burgstaller okhttp digest 1 13 import android span class hljs preprocessor content span span class
  • ubuntu下git push失败error: 无法推送一些引用到 ‘xxx ‘解决方法

    如果你在Ubuntu下使用git push上传你的代码到gitee xff0c 突然出现一行报错 xff1a To git 64 gitee com imysy twenty two thread pool test git rejecte
  • 【Linux驱动开发】并发控制机制:原子操作、自旋锁、信号量、互斥锁详解

    并发控制机制 首先我们来了解一下 操作系统的并发性 这个概念 xff1a 操作系统的并发性 concurrence xff1a 指的是两个或者两个以上事件在同一时间间隔内发生 xff0c 即这个设备一会执行这个事件一会执行那个事件 xff0
  • STM32F051K8U6按键中断实例

    引言 最近要开始做毕设了 xff0c 准备用STM32做一个平衡小车 xff0c 好久没做过STM32的裸机项目了 xff0c 做几个项目练练手 xff0c 复习一下 本例程使用STM32CubeMX配套hal库来实现按键中断和串口中断 芯
  • STM32库函数笔记分享

    之前刚开始自学的部分STM32笔记放出 xff0c 希望对新入门STM32和想要复习库函数的小伙伴们起到帮助 建立工程 1 寄存器操作方式 需要不断地查手册来了解每一位是干什么用的 优点 xff1a 代码简介 xff1b 缺点 xff1a
  • rc.exe not found.(完美解决,亲测有效)

    完美解决rc exe not found 报错出错原因解决方法完美解决 报错 这两天安装了vs2015和IVF2016 xff0c 安装完之后在运行程序的时候一直会出现rc exe not found xff0c 重新生成解决方案后还是一样
  • 单片机与上位机通过串口通信--笔记

    定义 先说什么是串口 xff1f xff08 1 xff09 他是一种通信接口 xff0c 单片机 IO 口上的复用功能 xff0c 上位机 xff08 电脑 xff09 和下位机 xff08 开发板 xff09 之间的数据传输 xff08
  • Qt 的Cmake方式如何创建资源文件

    传统的qmake创建的工程有pro qrc xff0c 但是如果使用cmake方式创建的工程就没有这两个东西 xff0c 我们公司就是在linux下使用cmake创建的Qt工程 xff0c 没有pro也看不到qrc xff0c 想在ui界面
  • 理解ROS Topic 通信频率背后的机制

    Topic是ROS的三种通信方式中最为基本 也是常用的一种 本文对于ROS的Topic通信背后的数据吞吐机制做一个较为详细 深入的介绍 Publisher ROS中发布一个topic的函数是这样的 ros span class token
  • Linux应用层例程4 串口应用编程

    本小节我们来学习 Linux 下串口应用编程 xff0c 串口 xff08 UART xff09 是一种非常常见的外设 xff0c 串口在嵌入式开发领域当中一般作为一种调试手段 xff0c 通过串口输出调试打印信息 xff0c 或者通过串口
  • Linux应用层例程7 CAN 应用编程基础

    CAN 是一种多主方式的串行通讯总线 xff0c 基本设计规范要求有高的位速率 xff0c 高抗电磁干扰性 xff0c 而且能够检测出产生的任何错误 经过几十年的发展 xff0c 现在 xff0c CAN 的高性能 高可靠性以及高实时性已被