HAL库STM32常用外设—— CAN通信(一)
文章目录
- 一、CAN是什么?
- 1.1 CAN应用场景
- 1.2 CAN通信优势
- 二、CAN基础知识介绍
- 2.1 CAN总线结构
- 2.2 CAN总线特点
- 2.2.1 CAN总线的数据传输特点
- 2.2.2 位时序和波特率
- 2.3 CAN位时序和波特率
- 2.3 CAN物理层
- 2.3.1 CAN 物理层特性
- 2.3.2 CAN 收发器芯片介绍
- 2.4 CAN协议层
- 2.4.1 CAN帧种类介绍
- 2.4.2 标准格式数据帧与遥控帧
- 2.4.3 扩展格式数据帧和遥控帧
- 三、CAN外设工作原理和HAL驱动程序
- 3.1 片上CAN外设的功能概述
- 3.2 CAN模块的基本控制
- 3.2 CAN模块的测试模式
- 3.3 消息发送
- 3.4 消息接收
- 3.5 标识符筛选
- 3.5.1 标识符筛选原理
- 3.5.2 函数HAL_CAN_ConfigFilter()
- 3.6 中断及处理
- 3.6.1 一个中断和中断事件
- 3.6.2 发送中断的事件源和回调函数
一、CAN是什么?
CAN是控制器区域网络(Controller Area Network)的缩写。CAN总线是一种适用于工业设备的高性能总线网络。STM32G407有两个CAN控制器,开发板上也有CAN收发器,可以进行CAN总线网络的通信试验。
1.1 CAN应用场景
(1)汽车电子系统:CAN最初是为汽车电子系统设计的,用于连接各种电子控制单元(ECU),如发动机控制单元、制动系统控制单元、仪表板控制单元等。CAN允许这些ECU之间进行高速、可靠的数据交换,实现车辆的各种功能和系统的集成。
(2)工业自动化:CAN在工业自动化领域得到广泛应用。它可以用于连接各种工业设备,如传感器、执行器、PLC(可编程逻辑控制器)等。
(3)船舶和航空器系统:CAN也被用于船舶和航空器系统中。它可以用于连接各种船舶或飞机的电子设备和控制单元,如引擎控制、导航系统、通信设备等。
(4)医疗设备:CAN被广泛应用于医疗设备中,如医疗监测设备、医疗图像设备等。
军事和航天应用:CAN也被用于军事和航天领域的应用。
1.2 CAN通信优势
(1)实时性: CAN具有高度的实时性,能够在微秒级的时间内传输数据,适用于对通信速度要求较高的应用场景,如汽车电子系统、工业控制等。
(2)高可靠性: CAN采用差分信号传输和位级协议处理技术,具有较强的抗干扰能力和噪声抑制能力,能够在恶劣环境下稳定运行。
(3)多节点通信: CAN网络支持多达数百个节点的连接,每个节点可以同时发送和接收数据,灵活性高,适用于复杂的系统结构。
(4)优化帧格式: CAN使用了优化的数据帧格式,包括标准帧和扩展帧,可以灵活地满足不同数据传输需求,提高了数据传输效率。
(5)低成本: CAN芯片和设备成本相对较低,使其在大规模应用中具有经济优势。
(6)简化布线: CAN网络采用双线制,即CAN_H和CAN_L,布线简单,易于安装和维护。
(7)支持错误检测和处理: CAN具有丰富的错误检测和处理机制,包括奇偶校验、CRC校验、重发机制等,能够有效地保障数据传输的可靠性和完整性。
二、CAN基础知识介绍
1986年,德国从事汽车电子产品开发的BOSCH公司开发出面向汽车电子设备网络化控制的CAN通信协议。为此,CAN通过ISO11898以及ISO11592-2进行了标准环,成为一种国际标准。现在,CAN的高性能和可靠性已被认可,并被广泛应用于船舶、医疗设备、工业设备灯方面,特别是在汽车的控制方面,已经成为汽车网络的标准协议。
作为一种串行通信总线,如同I2C总线协议一样,CAN总线也有物理层定义和传输协议定义。
2.1 CAN总线结构
CAN总线网络的结构有闭环和开环两种形式。图1-1 是闭环结构的CAN总线网络,总线两端各接一个120Ω的终端电阻,两根信号线形成的回路。这种CAN总线网络由ISO11898标准定义,是高速、短距离的CAN网络,通信速率为125kbit/s到1Mbit/s,在1Mbit/s通信速率时,总线长达40m。
图1-2 是开环结构的CAN总线网络,两根信号线独立,各自串联一个2.2 kΩ的电阻。这中CAN总线网络由ISO11519-2标准定义,是低速、远距离的CAN网络,最高速率为125kbit/s。在40kbit/速率时,总线最长举例为1000m。
闭环结构适用于节点数量有限的小型网络、简单性要求高、可靠性要求高的场景。开环结构适用于大型网络,扩展性要求高,故障隔离要求高的场景。
CAN总线上只有两根信号线,即图1-1和图1-2的CANH和CANL,没有时钟同步信号。所以CAN是一种异步通信方式,与UART的异步通信方式类似,而SPI、I2C是以时钟信号同步的同步通信方式。
备注:
1、CAN通信中120Ω电阻作用
当CAN总线被用于闭环结构的网络时,总线的两端需要连接一个120Ω的电阻,这个电阻被称为终端电阻。这样做的目的是为了
(1)阻抗匹配
CAN总线的特性阻抗通常是120Ω。为了防止信号在总线末端反射,必须在总线的两端各接一个120Ω的终端电阻。阻抗匹配能有效吸收信号能量,防止反射回来的信号干扰主信号。
(2)少信号反射
信号在传输过程中,如果遇到阻抗不匹配的情况,会在总线末端产生反射波。这些反射波会与原始信号叠加,导致信号失真。通过在总线两端并联120Ω电阻,可以吸收这些反射波,保证信号传输的完整性。
(3)持总线电压水平
CAN总线采用差分信号传输,信号是通过CAN_H和CAN_L两根线的电压差来表示的。并联电阻可以帮助维持总线上的正确电压水平,确保信号的正确传输。
(4) 增加抗干扰能力
CAN总线设计用于高噪声环境,并联的终端电阻能帮助提高系统的抗干扰能力。通过吸收外界的电磁干扰并减少其对总线信号的影响,保证数据的可靠传输。
2.2 CAN总线特点
2.2.1 CAN总线的数据传输特点
(1)CAN总线上的节点既可以发送数据又可以接收数据,没有主从之分。但是在同一个时刻,只能有一个节点在发送数据,其他节点只能接收数据。
(2) CAN总线上的节点没有地址的概念。CAN总线上的数据是以帧为单位传输的。,帧又分为数据帧、遥控帧等多种帧类型,帧包含需要传输的数据或控制信息。
(3)CAN总线具有“线与”的特性,也就是当有两个字节同时向总线发送信号时,一个发送显性电平(逻辑0),另一个发送隐形电平(逻辑1),总线呈现为显性电平,这个特性被用于总线仲裁,也就是哪个节点优先占用总线进行发送操作。当没有数据发送时,终端电阻使总线保持在隐性电平。
(4)每个帧也有一个标识符(Indentifier,以下简称ID)。ID不是地址,它表示数据传输的类型,也可以用于总线仲裁时确定优先级。例如,在汽车的CAN总线上,假设用于碰撞检测的节点输出数据帧的ID为01,车内温度检测节点发送数据帧的ID为05等。
(5) 每个CAN节点都接收数据,但是可以对接收的帧ID进行过滤。只有节点需要的数据才会被接收并进一步处理,不需要的数据会被自动舍弃。例如,假设安全气囊控制器只接收碰撞检测节点发出的ID为01的帧,这种ID的过滤是由硬件完成的,以便安全气囊控制器在发生碰撞时能及时响应。
(6)CAN总线通信是半双工的,即总线不能同时发送和接收。在多个节点竞争总线进行发送时,通过ID的优先级进行仲裁,竞争胜出的节点继续发送,竞争失败的节点立刻转为接送状态。
(7)CAN总线没有用于同步的时钟信号,所以需要规定CAN总线通信的波特率,所有节点都使用相同的波特率进行通讯。
2.2.2 位时序和波特率
一个CAN网络需要规定一个通信的波特率,各个节点都以相同的波特率进行数据通信。位时序指的是一个节点采集CAN总线上的一个位数据的时序,位时序如图 所示。通过位时序的控制,CAN总线可以进行位同步,以吸收节点时钟差异产生的波特率误差,保证接收数据的准确性。
2.3 CAN位时序和波特率
一个CAN网络需要规定一个通信的波特率,各节点都以相同的波特率进行数据通信。位时序指的是一个节点采集CAN总线上的一个位数据的时序。通过位时序的控制,CAN总线可以进行位同步,以吸收节点时钟差异产生的波特率误差,保证接收数据的准确性。
标称位时间指的是传输一个位数据的时间,用于确定CAN总线到的波特率。这个时间被分成了3段,
(1) 同步段(SYNC_SEG):在这个时间段内,总线上应该发生一次位信号的跳变。如果节点在同步段检测到总线上的一个跳变沿,就表示节点与总线是同步的。
(2)位段1(Bit Segment 1,BS1):定义了采样点的位置。在BS1结束的时间点对总线采样,得到的电平就是这个位的电平。BS1的初始长度是1到16个Tq,但它的长度可以在再同步(resynchronization)的时候被自动加长,已补偿各节点频率差异导致的正相位偏移。
(3)位段2(Bit Segment 2,BS2):定义了发送点的位置。BS2的初始长度是1到8个Tq,再同步时可以被自动缩短,以补偿负相位漂移。
CAN控制器可以自动对位时序进行同步,再同步时自动调整BS1和BS2的长度,位段加长或缩短的上限称为再同步跳转宽度(Resynchronization Jump Width ,SJW),SJW的取值是1到4个Tq。
CAN总线的波特率就是由标称位时间长度NBT决定,而NBT是位时序3个段的时间长度,即
2.3 CAN物理层
2.3.1 CAN 物理层特性
CAN总线的两根信号线通常采用双绞线,传输的是差分信号,通过两根信号线的电压差CANH - CANL来表示CAN的总线电平。以差分信号传输信号具有抗干扰强,能有效抑制外部电子干扰等优点,这也是CAN总线在工业上应用广泛的一个原因。使用差分信号表示总线电平的还有RS485网络,也是一种常用的工业现场总线。
两根信号线的电压差CANH-CANL表示CAN总线的电平,与传输的逻辑信号1和逻辑0对应。对于逻辑1的称为隐形(Ressive)电平,对应与逻辑0的称为显性(Dominant)电平。
对应于逻辑1和逻辑0,开环结构和闭环结构CAN网络的CANH和CANL的电压值不一样,隐形电平和显性电平的电压值也不一样。两种网络结构下的CAN总线信号典型电压如表1-1所示。
电平 | 闭环(高速) | 开环(低速) |
---|---|---|
显性电平(0) | UCAN_H – UCAN_L= 2V | UCAN_H – UCAN_L = 3V |
隐形电平(1) | UCAN_H – UCAN_L = 0V | UCAN_H – UCAN_L = - 1.5V |
2.3.2 CAN 收发器芯片介绍
在图1-1和图1-2的CAN总线网络中,CAN总线上的一个终端设备称为一个节点(Node),在CAN网络中,没有主设备和从设备的区别。一个CAN节点的硬件部分一般由CAN控制器和CAN收发器两个部分组成。CAN控制器负责CAN总线的逻辑控制,实现CAN传输协议;CAN收发器主要负责MCU逻辑电平与CAN总线电平之间的转换。
CAN控制器一般是MCU的片上外设(单片机芯片内部的各种功能模块和接口),例如,STM32F407有两个控制器。CAN收发器一般是单独的芯片,并且根据CAN总线的结构不同,需要使用不同的CAN收发器芯片,常见的CAN收发器芯片有TJA1050,TJA1042,SIT1050T,SIT1050T支持高速CAN,传输速率可达1Mbps,STM32F407开发板上使用的CAN收发器芯片是TJA1050。
引脚 | 功能 |
---|---|
D | CAN发送引脚 |
GND | 地 |
VCC | 供电(5V) |
R | CAN接收引脚 |
RS | 高速/静音模式选择(低电平为高速) |
CANH | 高电压CAN电压输入输出端 |
CANL | 低电位CAN电压输入输出端 |
Vref | 参考电压输出(此处悬空) |
2.4 CAN协议层
2.4.1 CAN帧种类介绍
CAN总线以“帧”形式进行通信。CAN协议定义了5种类型的帧:数据帧、遥控帧、错误帧、过载帧、间隔帧,其中数据帧最为常用。
其中,数据帧和遥控帧有ID,并且有标准格式和拓展格式两种格式,标准格式的ID是11位,拓展格式的ID是29位,下面仅详细介绍数据帧和遥控帧的结构,其他帧的结构可参考相关资料。
2.4.2 标准格式数据帧与遥控帧
标准格式数据帧和遥控帧的结构如图 所示,它们都有11位的ID。数据帧传输带有ID的0到8字节的数据;遥控帧只有ID,没有数据,用于请求数据。
数据帧可以分为以下几段。
(1)帧起始(Start Of Frame,SOF)。帧起始只有一个位,是一个显性电平(逻辑0),表示一个帧的开始。
(2)仲裁段(Arbitration Field)。仲裁段包括11位的ID和RTR位,共12位。多个节点竞争总线发送数据时,根据仲裁段的数据决定哪个节点优先占用总线。哪个ID先出现显性电平(逻辑0),对应的节点就占用总线。所以,ID数值越小的优先级更高(CAN总线使用的是基于标识符的仲裁机制,标识符中的低位具有较高的权重,因此ID数值小的节点的标识符具有更高的优先级)。如果两个节点发送数据帧的ID相同,再根据仲裁段最后的RTR位进行裁决。
RTR(Remote Transmit Request)是远程传输请求位,RTR位用于区分数据帧和遥控帧。数据帧的RTR位是显性电平(逻辑0),遥控帧的RTR位是隐形电平(逻辑1)。所以,具有相同ID的数据帧和遥控帧竞争总线时,数据帧优先级更高。
(3)控制段。控制段包括IDE位、RB0位和4位的DLC,共6位。
IDE是标识符扩展位(Identifier Extension Bit),用于表示帧是扩展格式还是标准格式。标准格式的IDE是显性电平(逻辑0),拓展格式帧的IDE是隐形电平(逻辑1)。
RB0是保留位,默认为显性电平。
DLC是4个位的数据长度编码(Data Length Code),编码数值为0到8,表示后面数据段的字节,遥控帧的DLC编码数值为0,因为遥控帧不传输数据。
(4)数据段。数据段里面是数据帧需要传输的数据,可以是0到8字节,数据的字节个数由DLC编码确定。遥控帧没有数据段。
(5)CRC段。检查帧的传输错误的段。CRC共16位,其中前15位是CRC校验码,最后一位总是隐形电平,是CRC段的界定符(Delimiter)。
(6)ACK段。ACK段包括一个ACK位(Acknowledge Bit)和一个ACK段界定符。发送节点发送的ACK位是隐形电平,接收节点接收的ACK位是显性电平。
(7)帧结束(End Of Frame,EOF)。帧结束是帧结束段,由7个隐性位表示EOF。
数据帧或遥控帧结束后,后面一般是帧空间或过载帧,用于分隔开数据帧和遥控帧。
2.4.3 扩展格式数据帧和遥控帧
扩展格式数据帧和遥控帧的结构如图所示。扩展格式的ID总是29位,扩展格式帧与标准格式帧的差异在于仲裁段和控制段。
(1)仲裁段。扩展格式数据帧的仲裁段总共32位,包括11位标准ID、SRR位、IDE位、18位扩展ID、RTR位。
SRR位(Substitue Remote Request Bit)只存在于拓展格式帧中,用于替代标准格式帧中的RTR位。SRR位总是隐形电平,相当于一个占位符,真正的RTR位在仲裁段的最后一位。RTR位还是用于区分数据帧和遥控帧。
扩展帧格式帧的IDE位总是隐形电平,表示这是扩展格式的帧。
(2)控制段。控制段由RB1位、RB0位和4位DLC组成。RB1位和RB0位是保留位,总是显性电平。4位的DLC编码表示数据的长度,从0到8字节。
三、CAN外设工作原理和HAL驱动程序
3.1 片上CAN外设的功能概述
STM32F4系列器件上有两个基本扩展CAN(Basic Extended CAN,bxCAN),被称为bxCAN外设,支持2.0A和2.0B的CAN协议。在本节中,我们将bxCAN外设还是简称为CAN外设,两个CAN外设是CAN1和CAN2,称它们为CAN模块。
STM32F4系列器件的两个CAN模块的结构如图3-1 所示,CAN1是带有512字节的SRAM的主CAN控制器,CAN2无法直接访问SRAM存储器,是从CAN控制器。两个CAN控制器共享512字节的SRAM。
STM32F4的CAN外设的主要特点如下:
(1)波特率最高为1Mbit/s。
(2)每个CAN模块有3个发送邮箱,可自动重发。
(3)具有16位自主运行的定时器,可以定时触发通信,可以在最后两个数据字节发送时间戳。
(4) 每个CAN模块有两个FIFO单元,每个FIFO有3个接收邮箱,每个FIFO有独立的中断地址。
(5)两个CAN模块共用28个筛选器组,筛选器用于配置可接收ID列表或掩码。数据帧和遥控帧根据ID被筛选,只有通过筛选的帧才能进入接收邮箱。帧的筛选完全由硬件完成,减少处理器的负担。
STM32F4系列MCU上的CAN模块只是CAN控制器,要构成图2-1和2-2 中的一个CAN节点,MCU还需要外接一个CAN收发器芯片,实现MCU逻辑电平到CAN总线物理层的电平转换和控制。
3.2 CAN模块的基本控制
CAN模块有3种主要的工作模式:初始化、正常和睡眠。硬件复位后,CAN模块处于睡眠模式;在初始化模式下,可以对CAN模块进行初始化设置;在正常模式下,可以进行数据的接收与发送。通过配置CAN主控制寄存器CAN_MCR的SLEEP、INRQ等位,用户可以实现在3种工作模式之间的转换。
HAL驱动程序中用于CAN模块初始化、工作模式转换、启动和停止的函数如表 所示
函数名 | 函数功能描述 |
---|---|
HAL_CAN_Init() | CAN模块初始化,主要是配置CAN总线通信参数 |
HAL_CAN_MspInit() | CAN模块初始化MSP弱函数,在HAL_CAN_Init() 里面被调用。需要用户程序重新实现,用于引脚GPIO配置,中断优先级配置 |
HAL_CAN_Start() | 启动CAN模块 |
HAL_CAN_Stop() | 停止CAN模块,允许重新访问配置寄存器 |
HAL_CAN_RequestSleep() | 使CAN模块在完成当前操作后进入睡眠模式 |
HAL_CAN_WakeUp() | 将CAN模块从睡眠模式唤醒 |
HAL_CAN_IsSleepActive() | 查询CAN模块是否处于睡眠模式,返回值位1表示模块处于睡眠模式 |
CAN模块的初始化函数是HAL_CAN_Init(),其原型定义如下:
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan);
其中,hcan是CAN_HandleTypeDef 结构体类型指针,是CAN模块对象指针。CAN_HandleTypeDef 的成员变量Init是结构体类型CAN_InitTypeDef,用于存储CAN通信参数。
在CubeMx生成的代码中,会为启用的CAN模块定义外设对象变量,例如:
CAN_HandleTypeDef hcan1;
表3-1中的其他函数的原型定义如下:
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_IsSleepActive(CAN_HandleTypeDef *hcan);
一个CAN模块需要先用函数HAL_CAN_Init()进行外设初始化,模块处于初始化模块,可以进行筛选器组的配置。执行函数HAL_CAN_Start()启动CAN模块进入正常模式,模块可以在正常模式和睡眠模式之间切换。执行HAL_CAN_Stop()将停止CAN模块。
3.2 CAN模块的测试模式
在对CAN模块进行初始化设置时,我们通过位时序寄存器CAN_BTR的SILM和LBKM位,可以使CAN模块进入测试模式。在测试模式下,我们将主控制寄存器CAN_MCR中的INRQ位复位,可以进入正常模式。要进入测试模式,必须在CAN模块初始化时进行设置。在测试模式下,CAN可以自发自收,已测试CAN模块的功能是否正常。使CAN模块进入某种测试模式是在初始化函数HAL_CAN_Init()中,通过设置CAN模块的属性实现的。CAN模块的3种测试模式如下图所示。
(1)静默模式(slient mode)。在静默模式下,CAN模块可以接收有效的数据帧和遥控帧,但是只能向总线发送隐性位,发送的显性位都被自己接收,所以在静默模式下,CAN模块无法启动发送操作。这种模式一般用于监测总线流量。
(2)环回模式(loop back mode)。在环回模式下,CAN模块可以正常的向总线发送数据,但是不能接收总线上的数据,只能接收自己发送的数据(需要通过筛选规则)。 这种模式可用于自检测试 。为了不受外部事件的影响,CAN内核在此模式下不会对数据或遥控帧的ACK采样,这样可以忽略ACK错误。
(3)环回与静默组合模式(loop back mode with silent mode)。这是环回与静默模式的组合,可用于“热自检”。在这种模式下,CAN模块不能接收总线上的数据,只能接收字节发送的数据;只能向总线上发送隐形位,因此不会影响CAN总线。
3.3 消息发送
一个CAN模块有3个发送邮箱。在发送数据时,用户需要选择一个空闲的发送邮箱,将标识符ID、数据的长度和数据(最多8字节)写入邮箱,然后CAN模块会自动控制将邮箱内容的数据发送出去。
用户可以设置自动重发,也就是在出现错误后自动重发,直至成功发送为止。如果禁止自动重发,则发送失败后不再重发,会通过发送状态寄存器CAN_TSR相应的位指示错误原因,如仲裁丢失或发送错误。
用户可以终止邮箱数据的发送,终止发送后邮箱会变成空闲状态。
用户可以设置时间触发通信模式(time trigggered communication mode)。在此模式下,会激活CAN模块内部的一个硬件计数器,CAN总线每收发一个数据,计数器都会递增。在发送或接收时,在帧的起始位时刻捕获结束之,作为发送或接收数据帧的时间戳数据。
在CAN的HAL库驱动程序中,与发送消息先关的函数如表3-2所示。
函数名 | 功能描述 |
---|---|
HAL_CAN_GetTxMailboxesFreeLevel() | 查询空闲的发送邮箱个数,空闲邮箱个数大于0时就可以发送 |
HAL_CAN_AddTxMessage() | 向一个邮箱写入一条消息,由CAN模块自动控制邮箱内消息的发送 |
HAL_CAN_AbortTxRequest() | 中止发送一个被挂起(等待发送)的消息 |
HAL_CAN_IsTxMessagePending() | 判断一个消息是否在等待发送 |
HAL_CAN_GetTxTimestamp() | 如果使用了时间触发通信模式,此函数读取发送消息的时间戳 |
函数HAL_CAN_GetTxMailboxesFreeLevel()用于查询一个CAN模块空闲的发送邮箱个数,如果有空闲的发送邮箱,就可以使用函数HAL_CAN_AddTxMessage()向发送邮箱写一条消息,然后由CAN模块启动发动过程。这个函数只能发送数据帧或遥控帧,其函数原型定义如下:
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);
其中,参数hcan是CAN模块外设对象指针;参数pHeader是CAN_TxHeaderTypeDef结构体类型指针,定义了消息的一些参数;aData是发送数据的数组,最多8字节的数据;参数pTxMailbox用于返回实际使用的发送邮箱号。
结构体CAN_TxHeaderTypeDef用于定义消息的一些参数,用于CAN模块组装成数据帧,该结构体完整定义如下:
typedef struct
{ uint32_t StdId; //11位的标准标识符,设置范围是0~0x7FFuint32_t ExtId; //29位的扩展标识符,设置范围是0~0x1FFFFFFFuint32_t IDE; //帧格式类型,标准ID(CAN_ID_STD)或扩展ID(CAN_ID_EXT)uint32_t RTR; //RTR位,消息类型;数据帧(CAN_RTR_DATA)或遥控帧(CAN_RTR_REMOTE) uint32_t DLC; //数据字节数,最多8字节 FunctionalState TransmitGlobalTime; //是否使用时间戳,取值ENABLE或DISABLE
} CAN_TxHeaderTypeDef;
其中,成员变量IDE表示帧格式类型,有两个宏定义表示标准帧ID和扩展帧ID。
#define CAN_ID_STD (0x00000000U) //标准ID
#define CAN_ID_EXT (0x00000004U) //扩展ID
成员变量RTR表示消息类型,只能是数据帧或遥控帧,有两个宏定义用于此变量的取值。
#define CAN_RTR_DATA (0x00000000U) //数据帧
#define CAN_RTR_REMOTE (0x00000002U) //遥控帧
CAN模块发送数据是将消息写入模块的发送邮箱,然后由CAN控制器将邮箱内的消息发送出去。CAN模块发送消息只有HAL_CAN_AddTxMessage()这一个函数,不想串口、SPI等其他外设有中断模式、DMA方式的专用函数 。
将消息写入邮箱后,可以用函数HAL_CAN_IsTxMessagePending()查询邮箱内的消息是否发送出去了,这个函数的原型定义是:
uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
其中,参数TxMailboxes是发送邮箱号。函数返回值如果是0,则表示没有等待发送的消息,也就是消息已经发送出去了;如果返回值为1,则表示邮箱内的消息仍然在等待发送。CAN总线可能有多个节点,需要通过总线仲裁获得CAN总线使用权以后,节点才能就爱那个邮箱里面的消息发送出去。
CAN模块也有表示表示消息发送出去的中断事件,如果打开了相应的中断事件使能控制位,也可以在中断里做出响应
3.4 消息接收
每个CAN模块有两个接收FIFO(Receive FIFO),每个接收FIFO有3个邮箱。 FIFO完全由硬件管理,当有有相机接收到有效消息时,就会产生相应的事件中断标志,可以产生CAN RX硬件中断。接收FIFO0和接收FIFO1有各自的中断地址。用户可以通过轮询方式或中断方式读取接收邮箱中的消息。CAN模块接收消息的相关函数如表3-3 所示。
从邮箱中读出消息后,邮箱就自动释放。如果一个接收FIFO的3个邮箱都接收到消息而没有及时读出,再有消息进入时就会产生上溢。根据是否设置接收FIFO锁定,有两种处理方式。
(1) 如果禁止接收FIFO锁定,则新传入的消息会覆盖FIFO中存储的最后一条消息 。
(2) 如果开启FIFO锁定,则新传入的消息会被舍弃 。
注:下面代码中的“ReceiveFifoLocked”就是配置的接收FIFO锁定功能,如果设置为Disable,表示FIFO上溢不锁定,下一条新消息覆盖前一条消息。如果设置为Enable,则表示上溢锁定后,丢弃下一条新消息。
函数名 | 功能描述 |
---|---|
HAL_CAN_GetRxFifoFillLevel() | 查询一个FIFO中存在未读取消息的邮箱个数 |
HAL_CAN_GetRxMessage() | 读取一个接收邮箱中的消息 |
函数HAL_CAN_GetRxFifoFillLevel()用于查询某个FIFO存在未读消息的邮箱个数,函数原型定义如下:
uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *hcan, uint32_t RxFifo);
其中,参数RxFifo是FIFO编号,一个CAN模块有两个FIFO,可使用如下的两个宏定义最为此参数的取值。
#define CAN_FILTER_FIFO0 (0x00000000U) //CAN模块FIFO0
#define CAN_FILTER_FIFO1 (0x00000001U) //CAN模块FIFO1
如果查询到有未读取的消息,就用函数HAL_CAN_GetRxMessage() 读取接收的消息,此函数的原型定义如下:
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
其中,参数RxFifo是FIFO编号,用宏CAN_FILTER_FIFO0和CAN_FILTER_FIFO1分别表示FIFO0和FIFO1,参数pHeader是CAN_RxHeaderTypeDef结构体类型指针,记录了帧的一些消息,aData[]是接收数据的数组,最多8字节。
记录帧信息的结构体CAN_RxHeaderTypeDef的定义如下:
typedef struct
{uint32_t StdId;//11位的标准标识符,设置范围是0~0x7FF uint32_t ExtId;//29位的扩展标识符,设置范围是0~0x1FFFFFFF uint32_t IDE;//帧格式类型,标准ID(CAN_ID_STD)或扩展ID(CAN_ID_EXT) uint32_t RTR;//RTR位,消息类型;数据帧(CAN_RTR_DATA)或遥控帧(CAN_RTR_REMOTE) uint32_t DLC; //数据字节数,最多8字节 uint32_t Timestamp; //时间戳数据,数值范围是0~0xFFFFuint32_t FilterMatchIndex;//匹配的筛选器索引
} CAN_RxHeaderTypeDef;
结构体CAN_RxHeaderTypeDef的部分成员变量与结构体CAN_TxHeaderTypeDef的相同,只有后面两个成员变量是CAN_RxHeaderTypeDef特有的。
3.5 标识符筛选
3.5.1 标识符筛选原理
在CAN网络中,发送节点是以广播方式发送消息的,所有CAN节点都可以接收到消息。数据帧和遥控帧带有标识符,标识符一般表示了消息的类型。一个CAN节点一般只对特定的消息感兴趣,如果用软件对接收帧的ID进行判别,将消耗接收节点的大量CPU时间。从图 中可以看出,STM32F4的两个CAN控制器有28个共用的标识符筛选器(Fliter Bank),可以完全用硬件的方式接收的帧ID进行筛选,只允许符合条件的帧进入接收邮箱,自动放弃不符合条件的帧。
每个筛选器组包含两个32个寄存器,分别是CAN_ExR1和CAN_FxR2。这两个寄存器可以被配置为两个32位长度筛选器或4个16位长度筛选器,筛选器可以是掩码模式或列表模式。所以一个筛选器组有4种配置模式。
(1)1个32位筛选器——标识符掩码模式。在这种模式下,寄存器CAN_FxR1存储一个32位ID标识符,这个ID与11位标准ID(STID[10:0])、18位扩展ID(EXID[17:0])、IDE位、RTR位的位置对应关系如图 中的模式(1)所示。IDE为0时表示标准格式帧,否则表示扩展格式帧。
CAN_FxR2存储一个32位掩码,如果掩码为1,则表示该位必须与ID中的位一致,如果为0,则表示不用一致。
例如,如果让一个CAN节点只接收标准ID为奇数的标准格式数据帧,则设置寄存器CAN_FxR1表示的ID时,STID[0]位必须设置为1,IDE位必须设置为0(表示标准格式帧),RTR位必须设置为0(表示数据帧)。设置寄存器CAN_FxR2表示的掩码时,对应的这些位必须设置为1,其他位设置为0。ID和掩码的设置结果如表 所示,表中位的数据为“X”表示这个位可以为0,也可以为1。
(2)2个32位筛选器——标识符列表模式。在这种模式下,寄存器CAN_FxR1和CAN_FxR2各存储一个32位的ID,ID的组成与模式(1)相同。只有匹配这两个ID的帧才能通过筛选。
(3)2个16位筛选器——标识符掩码模式。在这种模式下,寄存器CAN_FxR1的高16位组成一个ID,低16位组成一个掩码;寄存器CAN_FxR2的高16位组成一个ID,低16位组成一个掩码。16位的ID组成如图 中的模式(3)所示。
(4)4个16位筛选器——标识符列表模式。在这种模式下,寄存器CAN_FxR1表示2个16位ID,寄存器CAN_FxR2表示2个16位ID,16位ID的组成如图 中的模式(4)所示。
用户可以为一个FIFO设置多个筛选器,但是一个筛选器组只能配置成一个FIFO。如果FIFO设置了筛选器,并且接收的帧与所有的筛选器都不匹配,那么该帧就会被舍弃。只要通过了一个筛选器,帧就会被存入接收邮箱。
3.5.2 函数HAL_CAN_ConfigFilter()
函数HAL_CAN_ConfigFilter()用于设置CAN模块的标识符筛选器,应该在执行HAL_CAN_Start()启动一个CAN模块之前调用这个函数 。其原型定义如下:
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig);
其中,参数sFilterConfig是结构体CAN_FilterTypeDef类型指针,它保存了筛选器的设置,这个结构体定义如下,各成员变量的意义见注释:
typedef struct
{uint32_t FilterIdHigh;//CAN_FxR1寄存器的高16位,取值范围为0~FFFF uint32_t FilterIdLow; //CAN_FxR1寄存器的低16位,取值范围为0~FFFF uint32_t FilterMaskIdHigh; //CAN_FxR2寄存器的高16位,取值范围为0~FFFF uint32_t FilterMaskIdLow; //CAN_FxR2寄存器的低16位,取值范围为0~FFFF uint32_t FilterFIFOAssignment; //筛选器应用于哪一个FIFO,使用宏CAN_FILTER_FIFO0或CAN_FILTER_FIFO1uint32_t FilterBank; //筛选器编号,具有双CAN模块的MCU有28个筛选器,编号范围为0~27 uint32_t FilterMode;//筛选器模式,ID掩码模式(CAN_FILTERMODE_IDMASK) 或ID列表模式(CAN_FILTERMODE_IDLIST) uint32_t FilterScale; //筛选器长度。即32位(CAN_FILTERSCALE_32BIT)和16位(CAN_FILTERSCALE_16BIT) uint32_t FilterActivation; //是否启用此筛选器,ENABLE或DISABLEuint32_t SlaveStartFilterBank;//设置应用于从CAN控制的筛选器的起始编号
} CAN_FilterTypeDef;
某些变量的取值具有相应的宏定义,例如,FilterMode 是筛选器模式,有两个宏定义可用于此变量的取值,宏定义如下:
#define CAN_FILTERMODE_IDMASK (0x00000000U) //ID掩码模式
#define CAN_FILTERMODE_IDLIST (0x00000001U) //ID列表模式
3.6 中断及处理
3.6.1 一个中断和中断事件
一个CAN模块有4个中断,对应4个ISR。例如,CAN1的4个中断及其ISR 如表所示,下面以CAN1为例说明。
中断名称 | 中断中文名称 | 说明 | ISR名称 |
---|---|---|---|
CAN1_TX | 发送中断 | 任何一个发送邮箱发送完成时产生的中断 | CAN1_TX_IRQHandler() |
CAN1_RX0 | FIFO0接收中断 | FIFO0接收消息、满或上溢时产生的中断 | CAN1_RX0_IRQHandler() |
CAN1_RX1 | FIFO1接收中断 | FIFO1接收消息、满或上溢时产生的中断 | CAN1_RX1_IRQHandler() |
CAN1_SCE | 状态改变和错误中断 | 状态改变或发生错误时产生的中断 | CAN1_SCE_IRQHandler() |
每个中断又有1个或多个中断事件源,HAL库驱动程序中位每个中断事件源定义了中断类型宏定义,也就是中断事件使能控制位的宏定义。例如,CNA_TX1只有一个中断事件源,为其定义中断事件类型的宏定义如下:
#define CAN_IT_TX_MAILBOX_EMPTY ((uint32_t)CAN_IER_TMEIE)
HAL驱动程序中有两个宏定义可以开启或禁止某个具体的中断事件源。
__HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__)
__HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__)
其中__HANDLE__是CAN模块对象指针,__INTERRUPT__是表示中断事件类型的宏,例如
CAN_IT_TX_MAILBOX_EMPTY 。
在CubeMx为CAN模块的4个硬件中断生成的ISR中,都调用了 函数HAL_CAN_IRQHandler(),这是CAN中断处理通用函数 。函数HAL_CAN_IRQHandler()会根据中断使能寄存器、中断标志寄存器中的内容判断具体发生了哪个中断事件,再调用相应的回调函数。CAN的HAL驱动程序中为常用的中断事件定义了回调函数,只要搞清楚中断事件与回调函数的对应关系,编程时重现实现关联的回调函数,就可以对某个中断事件做出处理。
3.6.2 发送中断的事件源和回调函数
发送中断(CAN_TX)只有一个中断事件源CAN_IT_TX_MAILBOX_EMPTY,在3个发送邮箱中任何一个发送完成时都产生该事件中断,但是3个邮箱有各自的回调函数,如表 所示。
中断事件类型宏 | 中断事件说明 | 回调函数 |
---|---|---|
CAN_IT_TX_MAILBOX_EMPTY | 邮箱0发送完成 | HAL_CAN_TxMailbox0CompleteCallback() |
CAN_IT_TX_MAILBOX_EMPTY | 邮箱1发送完成 | HAL_CAN_TxMailbox1CompleteCallback() |
CAN_IT_TX_MAILBOX_EMPTY | 邮箱2发送完成 | HAL_CAN_TxMailbox2CompleteCallback() |
另外,调用函数HAL_CAN_AbortTxRequest()中止某个邮箱的发送后,也会调用相应的回调函数,如表 所示,只是这几个回调函数不是由中断引起的,而是由函数HAL_CAN_AbortTxRequest()引起的。
中断事件类型宏 | 中断事件说明 | 回调函数 |
---|---|---|
HAL_CAN_AbortTxRequest() | 邮箱0发送完成 | HAL_CAN_TxMailbox0CompleteCallback() |
HAL_CAN_AbortTxRequest() | 邮箱1发送完成 | HAL_CAN_TxMailbox1CompleteCallback() |
HAL_CAN_AbortTxRequest() | 邮箱2发送完成 | HAL_CAN_TxMailbox2CompleteCallback() |
注:CAN通信中120Ω电阻作用
1、区别:
时钟同步:同步通信需要发送方和接收方保持同步的时钟信号,而异步通信不需要。同步通信的数据传输是按照固定的时间间隔进行的,而异步通信的数据传输是按照数据帧的起始和停止位进行的。
数据传输方式:同步通信在发送和接收数据时,需要以固定的速率进行数据传输,发送方和接收方需要在特定的时钟脉冲到达时进行数据的发送和接收。异步通信在发送和接收数据时,通过起始位和停止位来确定每个数据帧的开始和结束。
应用场景:同步通信通常用于高速通信和对时序要求严格的应用,例如高速串行接口(如SPI、I2C)和以太网通信。异步通信通常用于低速通信和对时序要求不严格的应用,例如串口通信(如UART)、CAN通信和红外通信。
2、联系:
协议:无论是同步通信还是异步通信,都需要定义一种协议来规定数据的格式、传输方式和错误检测机制。常见的协议包括UART协议、SPI协议、I2C协议等。
相关文章:
HAL库STM32常用外设—— CAN通信(一)
文章目录 一、CAN是什么?1.1 CAN应用场景1.2 CAN通信优势 二、CAN基础知识介绍2.1 CAN总线结构2.2 CAN总线特点2.2.1 CAN总线的数据传输特点2.2.2 位时序和波特率 2.3 CAN位时序和波特率2.3 CAN物理层2.3.1 CAN 物理层特性2.3.2 CAN 收发器芯片介绍 2.4 CAN协议层2.…...
分页查询的实现
目录 前言 一.问题描述 二.后端实现步骤 2.1配置PageHelper插件 ①导入依赖 ②在application.yml配置文件中添加相关配置 2.2编写一个入门的程序,体验分页过程 2.3定义一个vo,用来收集分页后的所有信息 2.4修改serviceImpl层的代码 2.5动态设…...
Sourcetree——使用.gitignore忽略文件或者文件夹
一、为何需要文件忽略机制? 1.1 为什么要会略? 对于开发者而言,明智地选择忽略某些文件类型,能带来三大核心优势: 仓库纯净性:避免二进制文件、编译产物等污染代码库 安全防护:防止敏感信息&…...
Thinkphp的belongsToMany(多对多) 和 hasManyThrough(远程一对多)的区别是什么?
虽然 belongsToMany(多对多) 和 hasManyThrough(远程一对多) 都会使用 JOIN 查询,但它们的核心区别在于 关联关系的本质不同,具体如下: 1️⃣ belongsToMany(多对多) &a…...
DataWhale 大语言模型 - 大模型技术基础
本课程围绕中国人民大学高瓴人工智能学院赵鑫教授团队出品的《大语言模型》书籍展开,覆盖大语言模型训练与使用的全流程,从预训练到微调与对齐,从使用技术到评测应用,帮助学员全面掌握大语言模型的核心技术。并且,课程…...
Docker+Flask 实战:打造高并发微服务架构
DockerFlask 实战:打造高并发微服务架构 今天我们要深入探讨一个非常热门且实用的主题:基于 Docker 部署 Python Flask 应用。Docker 作为当下最流行的容器化技术,已经广泛应用于各种开发和部署场景,尤其是在微服务架构中。而 Fl…...
前端跨域如何调试,以及相关概念梳理【环境变量 本地代理 正向代理 反向代理 OPTIONS请求 CDN 等】
跨域报错 一 前端日常开发时,项目的部署地址和接口请求的地址一般是同源的,不会跨域。 例如项目的测试环境部署在https://my-dev.BeatingWorldLine.com/xxx, 测试环境的访问接口域名也要相同来保证不跨域https://my-dev.BeatingWorldLine.com/api/xxx, …...
【区块链】以太坊
学习视频源链接: https://www.bilibili.com/video/BV1Vt411X7JF/ 本文是根据肖老师的视频进行的笔记记录 bitcoin 1.0 区块链 以太坊 2.0区块链 以太坊 设置了 memory hard mining puzzle ,这造成了asic resistance, 后续 proof of work &a…...
MCU的工作原理:嵌入式系统的控制核心
MCU的工作原理可以概括为以下几个步骤: 1. 初始化 上电后,MCU从Flash存储器中加载程序代码,并初始化外设和寄存器。 2. 任务执行 根据程序逻辑,MCU执行数据处理、外设控制和通信等任务。通过中断系统实时响应外部事件。 3. 低…...
离线服务器ollama新增qwen2:0.5b模型
离线服务器ollama新增qwen2:0.5b模型 Dify集成ollama前面已经介绍过离线服务器CentOS使用的docker安装的ollama,其中在ollama中已经安装了deepseek-r1:1.5b。目前的需求是需要再安装一个qwen2:0.5b的模型,那么如何安装呢? 1.首先在有网的服…...
Ubuntu20.04安装运行DynaSLAM
目录 一、安装Anaconda 二、相关依赖库安装 1、boost安装 2、Eigen 3安装 3、opencv安装 4、Pangolin安装 三、配置Mask_RCNN环境 四、DynaSLAM编译 五、DynaSLAM运行 一、安装Anaconda 打开以下链接: Index of / 下载和自己系统匹配的安装包。这里下…...
Apache Shiro反序列化漏洞深度剖析:从原理到利用
引言 在Web安全的世界里,反序列化漏洞一直是最危险的漏洞类型之一。今天,我们将深入探讨Apache Shiro框架中的两个著名反序列化漏洞.通过通俗易懂的解释和详细的实例,帮助你理解这类漏洞的本质和危害。 Shiro框架与"记住我"功能简…...
Android UI 组件系列(二):Button 进阶用法
引言 在上一篇博客中,我们介绍了 Button 的基本用法和常见属性,掌握了 Button 的基础知识。然而,在实际开发中,Button 远不止于简单的点击功能,它还可以支持不同的变体、丰富的自定义样式,以及更灵活的状态…...
CentOS-7安装Docker(更新时间:2025-03-12)
CentOS-7安装Docker 该文章记录在CentOS 7上安装Docker的过程和步骤,以及在安装过程中遇到的困难和解决方案。 目录 CentOS-7安装Docker一、环境准备二、安装Docker1.验证服务器是否接入互联网2. 检查CentOS内核版本3.使用root权限登录CentOS。确保yum包更新到最新…...
网络空间安全(31)安全巡检
一、定义与目的 定义: 安全巡检是指由专业人员或特定部门负责,对各类设施、设备、环境等进行全面或重点检查,及时发现潜在的安全隐患或问题。 目的: 预防事故发生:通过定期的安全巡检,及时发现并解决潜在的…...
Kubernetes学习笔记-移除Nacos迁移至K8s
项目服务的配置管理和服务注册发现由原先的Nacos全面迁移到Kubernetes上。 一、移除Nacos 移除Nacos组件依赖。 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <…...
Docker 构建 nginx-redis-alpine 项目详解
Docker 构建 nginx-redis-alpine 项目详解 一、课程概述 嘿,朋友们!今天咱们要深入探索一个超级实用的项目 ——nginx-redis-alpine!这个项目可不简单,它包含了好多重要的知识点,像文件目录结构、核心文件的作用及配…...
【教学类-43-26】20240312 数独4宫格的所有可能(图片版 576套样式,空1格-空8格,每套65534张*576小图=3千万张小图)
背景需求: 之前做了三宫格所有可能图片 510小图*12套6120图,所以3分钟就生成了 【教学类-43-25】20240311 数独3宫格的所有可能(图片版 12套样式,空1格-空8格,每套510张,共6120小图)-CSDN博客…...
ChromeOS 134 版本更新
ChromeOS 134 版本更新 一、ChromeOS 134 更新内容 1. ChromeOS 自助终端(Kiosk)模式支持隔离 Web 应用(Isolated Web Apps) 从 ChromeOS 134 开始,自助终端(Kiosk)模式支持 隔离 Web 应用&a…...
Redis面试篇
目录 Redis面试篇 1.什么是Redis?作用是什么? 2.什么是缓存穿透、缓存击穿、缓存雪崩 2.1缓存穿透 2.2缓存击穿 2.3缓存雪崩 3.redis如何持久化 1. RDB(快照存储) 2. AOF(追加日志) 4.Redis 的过…...
C#中通过Response.Headers设置自定义参数
一、基础设置方法 1. 直接添加自定义头 // ASP.NET Core方案 Response.Headers.Append("X-API-Version", "2.3.1"); Response.Headers.Append("Custom-Auth-Token", Guid.NewGuid().ToString());• 底层原理:通过IHeaderDictionary…...
C++标准模板库学习--函数模板返回值参数类型
template<typename T1, typename T2> 2 T1 max (T1 a, T2 b) 3 { 4 return b < a ? a : b; 5 } 6 ... 7 auto m ::max(4, 7.2); // OK, 不过返回类型与第一个参数类型一样 如何解决模板的返回类型 法一,使用decltype进行类型推断,在编译时…...
BUG修复 | 一次钉钉工作台应用远程调试实战(开发者工具)
#1 ℹ️背景故事 最近用户反馈,钉钉工作台的应用无法正常使用,卡在自动登录页面。 天,这是运行10年的老程序😱,我当时真是吓得不轻。这老古董完全不记得怎么改了😂。 #2 🐞开启远程调试 钉钉…...
[目标检测] 训练之前要做什么
背景:训练一个Yolo8模型,在训练之前,数据集的处理是影响效果的关键因素。 Step1 定义规则 什么是人/车,比如人的话可能是站着的人,如果是骑电动车/自行车就不算是人。 Step2 收集数据集 1. 自己标注。如果是自己标…...
一窥DeepSeek开源EPLB项目:揭开技术背后的面纱
摘要 在DeepSeek开源DualPipe项目的同一天,EPLB项目也正式对外公开。EPLB(Enhanced Pipeline Balancing)并非一蹴而就的奇迹,而是经过长时间的研发与优化。该项目旨在通过改进管道平衡机制,提升系统的稳定性和效率。本…...
达梦数据库中插入导出图片的方法与应用
达梦数据库中插入导出图片的方法与应用 在数据库的实际应用场景中,图片存储是一项常见且重要的需求。以电商平台为例,商品展示图片是吸引消费者的关键元素;而在社交软件里,用户头像更是个人形象的直观体现。针对达梦数据库&#…...
问deepseek: OpenFOAM并行分区后,是如何实现ldumatrix矩阵向量乘法计算逻辑的?
在OpenFOAM中,lduMatrix 是用于存储稀疏矩阵的类,支持并行计算。并行分区后,lduMatrix 的矩阵向量乘法通过以下步骤实现: 1. 矩阵分区 分区:将矩阵和向量分配到多个处理器上,每个处理器负责一部分。接口&…...
linux(ubuntu)中Conda、CUDA安装Xinference报错ERROR: Failed to build (llama-cpp-python)
文章目录 一、常规办法二、继续三、继续四、缺少 libgomp库(最终解决)在 Conda 环境中安装 libgomp 如果符合标题情况 执行的: pip install "xinference[all]"大概率是最终解决的情况。 一、常规办法 llama-cpp-python 依赖 CMak…...
蓝耘携手通义万象 2.1 图生视频:开启创意无限的共享新时代
在科技飞速发展的今天,各种新奇的技术不断涌现,改变着我们的生活和工作方式。蓝耘和通义万象 2.1 图生视频就是其中两项非常厉害的技术。蓝耘就像是一个超级大管家,能把各种资源管理得井井有条;而通义万象 2.1 图生视频则像是一个…...
04 1个路由器配置一个子网的dhcp服务
前言 这是最近一个朋友的 ensp 相关的问题, 这里来大致了解一下 ensp, 计算机网络拓扑 相关基础知识 这里一系列文章, 主要是参照了这位博主的 ensp 专栏 这里 我只是做了一个记录, 自己实际操作了一遍, 增强了一些 自己的理解 当然 这里仅仅是一个 简单的示例, 实际场景…...
Android studio运行报错处理
没装HAXM报错: Intel HAXM 7.6.5 下载 下载链接: https://www.filehorse.com/download-intel-haxm/54766/download/#google_vignette 运行时弹窗提示:Device manager The emulator process for AVD Pixel_3a_API_34_extension_level_7_x86_6…...
【CXX】6.7 SharedPtr<T> — std::shared_ptr<T>
std::shared_ptr 的 Rust 绑定称为 SharedPtr。 限制: SharedPtr 不支持 T 为不透明的 Rust 类型。对于在语言边界上传递不透明 Rust 类型的所有权,应改用 Box(C 中的 rust::Box)。 示例 // src/main.rsuse std::ops::Deref; …...
NocoBase 本周更新汇总:双因素身份认证(2FA)
原文链接:https://www.nocobase.com/cn/blog/weekly-updates-202503013 汇总一周产品更新日志,最新发布可以前往我们的博客查看。 本周我们发布了 NocoBase 1.6.0 版本,带来集群模式部署、安全策略优化和迁移管理等多项新特性。 NocoBase …...
【Go学习】04-1-Gin框架-路由请求响应参数
【Go学习】04-1-Gin框架 初识框架go流行的web框架GinirisBeegofiber Gin介绍Gin快速入门 路由RESTful API规范请求方法URI静态url路径参数模糊匹配 处理函数分组路由 请求参数GET请求参数普通参数数组参数map参数 POST请求参数表单参数JSON参数 路径参数文件参数 响应字符串方式…...
DataX的python3使用
datax这东西本身是python2写的,这导致python3,就各种语法报错,问题是,现在的工程都是python3搞的,这就很难受.... 网上找到一篇帖子,可以解决这个问题: 原帖:python3执行datax报错…...
部署项目至服务器:响应时间太长,无法访问此页面?
在我们部署项目到服务器上的时候,一顿操作猛如虎,打开页面..... 这里记录一下这种情况是怎么回事。一般就是服务器上的安全组没有放行端口。 因为我是用宝塔进行项目部署的。所以遇到这种情况,要去操作两边(宝塔and服务器所属平台…...
Map<String,Object>中Fastjson提取entrys对应的值
今天在处理接口数据时,需要解析出对方传入的json数据,并需要取出其中一个字段的值来判断,记录下我的步骤,提供参考: 1.json数据准备 {"hrOrgUnit": "00000000-0000-0000-0000-000000000000CCE7AED4&q…...
【毕业论文格式】word分页符后的标题段前间距消失
文章目录 【问题描述】 分页符之后的段落开头,明明设置了标题有段前段后间距,但是没有显示间距: 【解决办法】 选中标题,选择边框 3. 选择段前间距,1~31磅的一个数 结果...
Android,Java,Kotlin 确保线程顺序执行的多种实现方式
在多线程编程中,有时需要确保一个线程必须等待另一个线程执行完毕后再执行。本文将介绍几种常见的方法来实现这一需求,并提供详细的代码示例。 1. 使用 Thread.join() Thread.join() 是最简单直接的方法,它会让当前线程等待目标线程执行完毕…...
AWK 入门教程:强大的文本处理工具
AWK 是一种强大的文本处理工具,广泛用于 Linux/Unix 系统中对文本文件或数据流进行操作。它能够基于条件筛选、统计字段、重新排列数据等。主要特点包括: 2. AWK 的基本语法 2.1 AWK 程序的结构 AWK 程序的结构: awk pattern { action } file 2.2 常…...
【Linux】在VMWare中安装Ubuntu操作系统(2025最新_Ubuntu 24.04.2)#VMware安装Ubuntu实战分享#
今天田辛老师为大家带来一篇关于在VMWare虚拟机上安装Ubuntu系统的详细教程。无论是学习、开发还是测试,虚拟机都是一个非常实用的工具,它允许我们在同一台物理机上运行多个操作系统。Ubuntu作为一款开源、免费且用户友好的Linux发行版,深受广…...
基于yolov8+streamlit实现目标检测系统带漂亮登录界面
【项目介绍】 基于YOLOv8和Streamlit实现的目标检测系统,结合了YOLOv8先进的目标检测能力与Streamlit快速构建交互式Web应用的优势,为用户提供了一个功能强大且操作简便的目标检测平台。该系统不仅具备高精度的目标检测功能,还拥有一个漂亮且…...
安装 Powerlevel10k 及 Oh My Zsh 的使用
1. 简介 Powerlevel10k 是 Oh My Zsh 最流行的终端主题,它不仅美观,还提供 Git 状态显示、命令执行时间、网络状态、Python 虚拟环境指示等 实用功能。相比其他主题,Powerlevel10k 速度更快、可定制性更强。 本教程将详细介绍如何安装 Powe…...
虚拟机下ubuntu进不了图形界面
6.844618] piix4_smbus 0000:07.3: SMBus Host ContrFoller not enabled! 7.859836] sd 2:0:0:0:0: [sda] Assuming drive cache: wirite through /dev/sda1: clean, 200424/1966080 files, 4053235/7864064 blocks ubuntu启动时,卡在上面输出位置 当前遇到的原因…...
从 root 一滴水看 Spring Data JPA 的汪洋大海
🔥 从 root 一滴水看 Spring Data JPA 的汪洋大海 🌊 在 Spring Data JPA 的世界里,Specification 是个让人又爱又恨的家伙 💡。它能帮你动态构建查询,但那个神秘的 Root<T> root 却总让人摸不着头脑࿱…...
二进制安装指定版本的MariaDBv10.11.6
一、官网下载mariadb安装包 Download MariaDB Server - MariaDB.org 找到对应的版本 下载安装包后上传到服务器这里不再赘述。 二、安装二进制包 1、解压安装包 2、查看安装包内的安装提示文档根据提示文档进行安装 # 解压安装包 tar xf mariadb-10.11.6-linux-systemd-x8…...
日志Python安全之SSTI——Flask/Jinja2
ssti的概念和模板引擎介绍等基础知识前面已经学过了,接下来直接进入正题 先了解flask/jinja2: flask: 用python编写的一个框架,集成 Jinja2 模板引擎(用于动态生成 HTML 内容)。 Flask 的核心组件&…...
梯度下降法以及随机梯度下降法
梯度下降法就是在更新weight的时候,向函数值下降的最快方向进行更新,具体的原理我就不再写了,就是一个求偏导的过程,有高数基础的都能够很快的理解过程。我在我的github里面会一直更新自己学习pytorch的过程,地址为&am…...
从零基础到能独立设计单片机产品,一般需要经历哪些学习阶段?
相信很多人,内心都有“钢铁侠”的幻想,成为能写程序,能设计硬件,能设计结构,能焊接的全能型人才。 上次徐工问我,如果你财富自由了,想去做啥? 我说出来,可能大家都不信&a…...
ORACLE 19.8版本遭遇ORA-600 [kqrHashTableRemove: X lock].宕机的问题分析
客户反馈单机环境的一个数据库半夜突然宕机了,这是一个比较重要的系统;接到通知后分析对应日志,发现ALERT日志中有明显报错:ORA-600 [kqrHashTableRemove: X lock]. 600报错我简单的分为2类,一类不会导致宕机&#x…...