STM32-CAN

news2025/1/13 15:50:51

一、CAN总线简介

1.1 CAN简介

CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO 国际标准化的串行通信
协议。异步半双工。
ISO11898:123kbps~1Mbps。

ISO11519:125kbps

特点:

  • 多主控制
  • 没有地址信息
  • 速度快,距离远
  • 具有错误检测、错误通知、错误恢复功能
  • 故障封闭功能
  • 多节点连接

1.1.1 ISO11898、ISO11519

帮助记忆:显“0”。多点线与机制,一个是0全是0,所有1才为1。类似于上拉。

差分信号:抗干扰,双绞线(相互抵消电磁干扰),电压差值不变。

1.2 CAN协议帧

  • 数据帧:发送单元向接收单元传送数据。
  • 遥控帧:接收单元向具有相同ID的发送单元请求数据的帧。
  • 错误帧:检测出错误,向其他单元通知错误。
  • 过载帧:接收单元通知为做好准备。
  • 间隔帧:将数据帧及遥控帧与前面的帧分隔开。

1.2.1 数据帧

1.2.1.1 帧起始(1bit)

1bit,显性电平。

1.2.1.2 仲裁段(12bit)
  • 显性电平获取优先。
  • 禁止高7位都为隐性电平(1111111XXXX)。标准:ID10~ID0。扩展:基本ID28~ID18,扩展ID17~ID0。
  • RTR:0数据帧,1远程帧
  • IDE:0标准,1扩展
  • SRR:代替RTR,隐性电平。

1.2.1.3 控制段(6bit)
  • r0,r1:保留,显性电平。
  • DLC:4bit,数据长度,MSB,0~8。

1.2.1.4 数据段(0~8bytes)
  • MSB

1.2.1.5 CRC段(16bit)
  • 计算:帧起始、仲裁段、控制段、数据段。

1.2.1.6 ACK段(2bit)
  • 发送单元:隐性,隐性。
  • 接收单元:显性,隐性。

1.2.1.7 帧结束(7bit隐性)

1.2.2 位时序

1位,分为4个段,每个段分为若干个Tq。

  • 同步段(SS):1Tq,
  • 传播时间段(PTS):1~8Tq,
  • 相位缓冲段1(PBS1):1~8Tq,
  • 相位缓冲段2(PBS2):2~8Tq,
  • 再同步补偿宽度(SJW):1~4T

1.2.3 位填充

当同样的电平持续 5 位时则添加一个位的反型数据。

发送单元的工作

在发送数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,在下一个位(第 6 个位)则要插入 1 位与前 5 位反型的电平。

接收单元的工作

在接收数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,需要删除下一个位(第 6 个位)再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧。

1.2.4 同步

硬件同步(帧起始同步);

再同步(发慢收快,延长相位缓冲段1;发快收慢,缩短相缓2)。

同步规则

  • 每位只同步一次。
  • 只有当上次采样点的总线值和边沿后的总线值不同时,进行同步。
  • 总线空闲从隐性到显性,硬件同步。

1.2.5 总线优先级

  • 在总线空闲态,最先开始发送消息的单元获得发送权。
  • 多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。
  • 具有相同 ID 的数据帧和遥控帧在总线上竞争时,仲裁段的最后一位(RTR)为显性位的数据帧具有优先权,可继续发送。(数据大于遥控)
  • 标准格式 ID 与具有相同 ID 的遥控帧或者扩展格式的数据帧在总线上竞争时,标准格式的 RTR 位为显性位的具有优先权,可继续发送。(标准大于扩展)

扩展知识:

STM32F1 自带的是 bxCAN,即基本扩展 CAN。它支持 CAN 协议 2.0A 和 2.0B。 CAN2.0A
只能处理标准数据帧,扩展帧的内容会识别错误; CAN2.0B Active 可以处理标准数据帧和扩展
数据帧;而 CAN2.0B passive 只能处理标准数据帧,扩展帧的内容会忽略。 它的设计目标是,
以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性
可软件配置)。

STM32F1 的 bxCAN 的主要特点有:
  • 支持 CAN 协议 2.0A 和 2.0B 主动模式
  • 波特率最高达 1Mbps
  • 支持时间触发通信
  • 具有 3 个发送邮箱
  • 具有 3 级深度的 2 个接收 FIFO
  • 可变的过滤器组(最多 28 个)

过滤器组的位宽和工作模式

为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。应用程序不用的过滤器组,应该保持在禁用状态。

优先级:32位>16位,标识符列表>屏蔽位,过滤号小的优先级高。

举例说明:过滤器组0工作在:1个32位过滤器-标识符屏蔽模式,CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00,

1.2.6 CAN收发流程

CAN发送

程序选择 1 个空置的邮箱(TME=1) →设置标识符(ID),数据长度和发送数据→设置 CAN_TIxR 的 TXRQ 位为 1,请求发送→邮箱挂号(等待成为最高优先级) →预定发送(等待总线空闲) →发送→邮箱空置。

CAN接收

FIFO 空→收到有效报文→挂号_1(存入 FIFO 的一个邮箱,这个由硬件控制,我们不需要理会) →收到有效报文→挂号_2→收到有效报文→挂号_3→收到有效报文溢出。

通过查询 CAN_RFxR 的 FMP 寄存器来得到,只要 FMP不为 0,我们就可以从 FIFO 读出收到的报文。

STM32的CAN位时间特性:

1.3 CAN寄存器

  • CAN_MCR:INRQ位,先设置为1,初始化,设置为0,正常工作。
  • CAN_BTR:设置分频,Tbs1,Tbs2及Tsjw等参数,进而设置波特率。可以设置环回模式。
  • CAN_TIxR:设置标识符,帧类型。TXRQ请求邮箱发送。x=0~3。
  • CAN_TDTxR:设置数据长度。
  • CAN_TDLxR、CAN_TDHxR:数据。
  • CAN_RIxR:设置接收标识符。
  • CAN_FM1R:设置28个过滤器的模式。
  • CAN_FS1R:设置各过滤器组的位宽。
  • CAN_FFA1R:设置报文存放的FIFO。
  • CAN_FA1R:过滤器激活寄存器。
  • CAN_FiRx:过滤器位。i=0~13,x=1或2。

二、程序设计

2.1 CAN的HAL驱动

HAL_CAN_Init函数

HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan);


typedef struct __CAN_HandleTypeDef
{
    CAN_TypeDef *Instance; /* CAN 控制寄存器基地址 */
    CAN_InitTypeDef Init; /* 初始化参数结构体 */
    __IO HAL_CAN_StateTypeDef State; /* CAN 通讯状态 */
    __IO uint32_t ErrorCode; /* CAN 通讯结果编码 */
} CAN_HandleTypeDef;

typedef struct
{
    uint32_t Prescaler; /* 分频值, 可以配置为 1~1024 间的任意整数 */
    uint32_t Mode; /* can 操作模式,有效值参考 CAN_operating_mode 的描述 */
    uint32_t SyncJumpWidth; /* CAN 硬件的最大超时时间 */
    uint32_t TimeSeg1; /* CAN_time_quantum_in_bit_segment_1 */
    uint32_t TimeSeg2; /* CAN_time_quantum_in_bit_segment_2 */
    FunctionalState TimeTriggeredMode; /* 启用或禁用时间触发模式 */
    FunctionalState AutoBusOff; /* 禁止/使能软件自动断开总线的功能 */
    FunctionalState AutoWakeUp; /* 禁止/使能 CAN 的自动唤醒功能 */
    FunctionalState AutoRetransmission; /* 禁止/使能 CAN 的自动传输模式 */
    FunctionalState ReceiveFifoLocked; /* 禁止/使能 CAN 的接收 FIFO */
    FunctionalState TransmitFifoPriority; /* 禁止/使能 CAN 的发送 FIFO */
} CAN_InitTypeDef;

HAL_CAN_ConfigFilter 函数

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan,
    CAN_FilterTypeDef *sFilterConfig)

typedef struct
{
    uint32_t FilterIdHigh; /* 过滤器标识符高位 */
    uint32_t FilterIdLow; /* 过滤器标识符低位 */
    uint32_t FilterMaskIdHigh; /* 过滤器掩码号高位(列表模式下,也是属于标识符) */
    uint32_t FilterMaskIdLow; /* 过滤器掩码号低位(列表模式下,也是属于标识符) */
    uint32_t FilterFIFOAssignment; /* 与过滤器组管理的 FIFO */
    uint32_t FilterBank; /* 指定过滤器组, 单 CAN 为 0~13, 双 CAN 可为 0~27 */
    uint32_t FilterMode; /* 过滤器的模式 标识符屏蔽位模式/标识符列表模式 */
    uint32_t FilterScale; /* 过滤器的位宽 32 位/16 位 */
    uint32_t FilterActivation; /* 禁用或者使能过滤器 */
    uint32_t SlaveStartFilterBank; /* 双 CAN 模式下,规定 CAN 的主从模式的过滤器分配 */
} CAN_FilterTypeDef;

HAL_CAN_Start 函数

HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);

HAL_CAN_ActivateNotification 函数

HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan,
    uint32_t ActiveITs);

HAL_CAN_AddTxMessage 函数

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan,
    CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)

typedef struct
{
uint32_t StdId; /* 标准标识符 11 位 范围:0~0x7FF */
uint32_t ExtId; /* 扩展标识符 29 位 范围:0~0x1FFFFFFF */
uint32_t IDE; /* 标识符类型 CAN_ID_STD / CAN_ID_EXT */
uint32_t RTR; /* 帧类型 CAN_RTR_DATA / CAN_RTR_REMOTE */
uint32_t DLC; /* 帧长度 范围:0~8byte */
FunctionalState TransmitGlobalTime; /* 时间戳是否在开始时捕获 */
} CAN_TxHeaderTypeDef;

HAL_CAN_GetRxMessage 函数

HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, 
uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])


typedef struct
{
    uint32_t StdId; /* 标准标识符 11 位 范围:0~0x7FF */
    uint32_t ExtId; /* 扩展标识符 29 位 范围:0~0x1FFFFFFF */
    uint32_t IDE; /* 标识符类型 CAN_ID_STD / CAN_ID_EXT */
    uint32_t RTR; /* 帧类型 CAN_RTR_DATA / CAN_RTR_REMOTE */
    uint32_t DLC; /* 帧长度 范围:0~8byte */
    uint32_t Timestamp; /* 在帧接收开始时开始捕获的时间戳 */
    uint32_t FilterMatchIndex; /* 过滤器匹配序号 */
} CAN_RxHeaderTypeDef;

2.2 CAN初始化配置步骤

1.CAN参数初始化

can_init(CAN_SJW_1TQ, CAN_BS2_8TQ, CAN_BS1_9TQ, 4, CAN_MODE_LOOPBACK);//500Kbps

2.开启CAN和对应管脚时钟,配置CAN_TX和CAN_RX的复用功能输出

3.设置过滤器

4.CAN数据接收和发送

/**
* @brief CAN 发送一组数据
* @note 发送格式固定为: 标准 ID, 数据帧
* @param id : 标准 ID(11 位)
* @retval 发送状态 0, 成功; 1, 失败;
*/
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{
    uint32_t TxMailbox = CAN_TX_MAILBOX0;
    g_canx_txheader.StdId = id; /* 标准标识符 */
    g_canx_txheader.ExtId = id; /* 扩展标识符(29 位) */
    g_canx_txheader.IDE = CAN_ID_STD; /* 使用标准帧 */
    g_canx_txheader.RTR = CAN_RTR_DATA; /* 数据帧 */
    g_canx_txheader.DLC = len;
    if (HAL_CAN_AddTxMessage(&g_canx_handler, &g_canx_txheader,
        msg, &TxMailbox) != HAL_OK) /* 发送消息 */
    {
        return 1;
    }
    /* 等待发送完成,所有邮箱为空(3 个邮箱) */
    while (HAL_CAN_GetTxMailboxesFreeLevel(&g_canx_handler) != 3);
    return 0;
}

/**
* @brief CAN 接收数据查询
* @note 接收数据格式固定为: 标准 ID, 数据帧
* @param id : 要查询的 标准 ID(11 位)
* @param buf : 数据缓存区
* @retval 接收结果
* @arg 0 , 无数据被接收到;
* @arg 其他, 接收的数据长度
*/
uint8_t can_receive_msg(uint32_t id, uint8_t *buf)
{
    if (HAL_CAN_GetRxFifoFillLevel(&g_canx_handler, CAN_RX_FIFO0) != 1)
    {
        return 0;
    }
    if (HAL_CAN_GetRxMessage(&g_canx_handler, CAN_RX_FIFO0, &g_canx_rxheader,
        buf) != HAL_OK)
    {
        return 0;
    }
    /* 接收到的 ID 不对 / 不是标准帧 / 不是数据帧 */
    if (g_canx_rxheader.StdId!= id || g_canx_rxheader.IDE != CAN_ID_STD ||
        g_canx_rxheader.RTR != CAN_RTR_DATA)
    {
        return 0;
    }
    return g_canx_rxheader.DLC;
}

三、常见问题

1、为什么用CAN?

汽车的电子控制单元逐渐增多。各电控单元之间的信号交换导致汽车线束的级数增加。大大减少了汽车的线束。可靠性下降。增加了重量。

2、如何减少波特率的误差带来的通信错误?

CAN总线规定信号的跳变沿时刻进行同步,将误差累计限制在两个跳变沿。 当发送数据出现都为0或者1的时候,同样不跳变造成误差累计怎么办? 采用填充位在连续5个相同位后插入一个相反位,产生跳变沿,用于同步。

3、终端电阻的作用

  • 提高抗干扰能力,让高频低能量信号快速走掉。
  • 确保总线快速进入隐性状态,让寄生电容的能量快速走掉。
  • 提高信号质量,放置在总线两端,让反射能量降低。

4、需要在接收数据的时候用一个标志来判断当前发送的数据是真正的命令还是干扰,用一个特殊的值来做为接收指令的开始,这里选用0XA5做为数据的开始,为什么选0xA5呢?

因为0xA5的 二进制数位 1010 0101 刚好是一个1一个0,间隔开,用这个数字做为开始可以很大程度上的避免干扰信号,因为干扰信号一般不会是这种高低高低很有规律的信号。于是协议就改为 0xA5 为第一个数据,做为上位机发送命令的标志。

5、CAN物理层常见故障(CAN示波器)

(1)CAN节点供电正常,CAN工具上就是接收不到CAN报文数据或者报错,可能是什么原因?

首先确定CAN器件程序有bug;终端电阻不匹配;CAN收发器的影响。

(2)测试CAN物理波形,发现报文出现严重的振铃和反射现象?

缩短引线长度;加粗到线、印制铜箔的宽度;减小信号的传输距离;采用引线电感小的元器件;阻抗匹配

(3)通信错误会不会是CAN收发器故障引脚,如何判断收发器的好坏?

可以在ECU上电的CAN总线空闲情况下,测量CANH和CANL对地的电压是否在2.5V左右,如果出现0V或5V之类的,可考虑收发器故障问题。

(4)来自想用厂家的两个CAN节点又可以正常通信,为什么两个不同厂家的CAN节点连接通信时好时坏,甚至不能正常通信?

不同的厂家使用不用的采样点,也有可能造成通信不良。

(5)所有在测ECU节点CAN功能单独测试正常,装车后CAN功能失常,CAN错误频发,特别是新能源车上?

电磁干扰:选择性能好的隔离收发器;增加CAN双绞程度;布线尽量远离;感性防护器件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1810842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高考后的家庭移民新选择

随着高考的落幕,您是否在思考未来的更多可能性?移民,作为一种生活选择,为许多家庭提供了一个全新的生活和教育环境。我们理解,每个家庭都希望为自己的孩子提供最好的未来。 移民国家通常拥有多元和包容的教育体系&…

Nginx Location匹配 和 Rewrite重写

前言:Nginx 正则表达式 ^匹配输入字符串的起始位置$匹配输入字符串的结束位置*匹配前面的字符零次或多次匹配前面的字符一次或多次?匹配前面的字符零次或一次.匹配除 “\n” 之外的任何单个字符\将后面接着的字符标记为一个特殊字符或一个原义字符或一个…

AI写作工具:提升工作效率的五大利器

不知道大家有没有发现,随着人工智能技术的快速发展,AI工具正逐渐渗透到我们日常生活的各个方面,极大地提高了我们的工作和学习效率。无论是AI写作、AI绘画、AI思维导图,还是AI幻灯片制作,这些工具已成为我们不可或缺的…

【计算机毕业设计】266基于微信小程序的在线点餐

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

49、Flink 的数据源的 SplitReader API 详解

SplitReader API a)概述 核心的 SourceReader API 是完全异步的,但实际上,大多数 Sources 都会使用阻塞的操作,例如客户端(如 KafkaConsumer)的 poll() 阻塞调用,或者分布式文件系统&#xff…

包装机故障排查与修复方法:确保生产线的稳定运行

在现代化的工业生产中,包装机作为生产线上的重要一环,其稳定运行直接关系到产品的质量和生产效率。然而,包装机在使用过程中难免会遇到各种故障,如何快速准确地排查并修复这些故障,确保生产线的稳定运行,成…

【Echarts系列】带图片的饼图

【Echarts系列】带图片的饼图 序前提说明示例数据格式代码动态旋转图片 序 为了节省后续开发学习成本,这个系列将记录我工作所用到的一些echarts图表。 前提说明 因为饼图中间需要添加图片,所以比较特殊,对于饼图中间数据的对齐很容易出现…

【npm】console工具(含胶囊,表格,gif图片)

这是一款控制台花样输出工具 相对丰富的输出方式 文本输出属性值输出胶囊样式输出表格输出图片输出(含动图) 安装 npm install v_aot引用 import v_aot from "v_aot";字段说明 字段类型属性字符串值字符串类型default 、 primary 、 suc…

Centos用自定义java安装包替换系统java版本

一.下载自定义安装java压缩包,比如 jdk-8u191-linux-x64.tar.gz 二.解压到/usr/java/ 下 tar -zxvf jdk-8u191-linux-x64.tar.gz 三.执行命令 update-alternatives --install /usr/bin/java java /usr/java/jdk1.8.0_191/bin/java 300 update-alternatives --i…

【全开源】旅游系统小程序(Uniapp+FastAdmin+ThinkPHP)

🌈暑假到来,旅游系统小程序助你畅游无忧!🎒 旅游系统,包含消费者端(手机端)、机构工作人员(手机端)、机构端(PC)、平台管理端(PC&…

Python基础速成

文件操作 文件读取 with open语法 文件写入 注意事项 文件追加 异常、模块与包 捕获异常 捕获方法 捕获传递 模块的导入与自定义 定义 导入方式 自定义 测试模块 注意事项 python包 定义 操作 第三方包 定义 pip指令安装包

实现思路:Vue 子组件高度不固定下实现瀑布流布局

实现思路:Vue 子组件高度不固定下实现瀑布流布局 一、瀑布流布局基础实现原理 在深入解说不定高度子组件的瀑布流如何实现之前,先大体说一下子组件高度固定已知的这种实现原理: 有一个已知组件高度的数组。定义好这个瀑布流的列数&#xff…

新概念英语视频百度云,新概念英语视频百度网盘,新概念1-4册

在现今数字化时代,英语学习资源丰富多样,其中新概念英语视频因其深入浅出的教学风格和丰富多样的学习内容,备受广大英语学习者的青睐。本文旨在为广大英语学习者提供一份详尽的新概念英语视频下载指南,帮助大家轻松获取优质学习资…

Macbook M芯片Homebrew与git的安装与配置

Macbook M芯片Homebrew与git的安装与配置 Homebrew的安装与配置 搜索Homebrew; 找到如下网址https://brew.sh/ 把以上命令复制到终端 执行后,发现并不能下载; 如果你像我一样也是不通的,可以使用国内源,将如下命令复制到终端:…

【C++题解】1750 - 有0的数

问题:1750 - 有0的数 类型:简单循环 题目描述: 请求出 1∼n 中含有数字 0 的数,有多少个? 输入: 一个整数 n(n≤999) 。 输出: 一个整数,代表 1∼n 中含…

关于Spring Security的CORS

目录 一、CORS是什么 二、同源安全策略 三、Spring Security中CORS的开启 四、其它处理方法 一、CORS是什么 CORS(Cross-Origin Resource Sharing,跨源/域资源共享 )是一个W3C标准,一种允许当前域(domain&#xff…

苹果WWDC揭晓AI系统、电脑等设备系统全线更新,iPhone将接入ChatGPT

iOS 18可自定义主屏幕、可卫星发短信、钱包App新增点击付款Tap to Cash功能、照片App大改、支持RCS短信;iPad首次有原生计算器App,iPad结合Apple Pencil拥有数学笔记功能;新版macOS可通过Mac查看控制iPhone,Safari有AI驱动的高亮显…

Docker:安装 Orion-Visor 服务器运维的技术指南

请关注微信公众号:拾荒的小海螺 博客地址:http://lsk-ww.cn/ 1、简述 Orion-Visor 是一种用于管理和监控容器的工具。它提供了一个直观的界面,用于查看容器的状态、资源使用情况以及日志等信息。在这篇技术博客中,我们将介绍如何…

01.FastLED库基础

FastLED库基础 FastLED库HSV颜色 HSV颜色基本概念 HSV颜色简介 HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色表达方法。该方法中的三个参数分别是:色调(H),饱和度(S&#…

Jenkins三种构建类型

目录 传送门前言一、概念二、前置处理(必做)1、赋予777权限2、让jenkins用户拥有root用户的kill权限3、要运行jar包端口号需要大于1024 三、自由风格软件项目(FreeStyle Project)(推荐)三、Maven项目&#…