STM32(HAL)——CAN通信

8. CAN

8.1 基本概念

全称Controller Area Network,是一种半双工,异步通讯。没有主从的说法,每个设备都可以发送和接收。

8.1.1 物理层

两条信号线,CAN_High和CAN_Low两条差分信号线,以差分形式通讯

两种网络形式:

闭环:允许总线最长40m,最高速1Mbps

在这里插入图片描述

∘ \circ 规定总线两端各有一个120Ω电阻。

∘ \circ CAN控制器是各个连接到总线上的设备的控制器,一般需要配备一个CAN收发器(比如咱们战队码盘上的CAN收发器用的是TJA1050),用于将CAN控制器的二进制码流转换为CAN总线的差分电平,在两条有差分电压的总线电缆上传输数据

开环:最大传输距离1Km,最高速125Kbps
在这里插入图片描述

∘ \circ 规定每根线串联一个2.2kΩ的电阻

CAN协议差分信号

在这里插入图片描述

∘ \circ 显性电平对应“0”,隐性电平对应“1”。隐性电平(1)两条线电压都是2.5V,即压差为0;显性电平(0)CAN_High和CAN_Low分别为3.5V和1.5V,压差为2V。

∘ \circ 总线上,只要有一个节点输出显性,则总线上为显性电平;只有所有节点都是隐性电平,总线才为隐性电平

∘ \circ 由于CAN是半双工的,收发分开进行,且是总线通讯,所以一个时刻只能有一个节点发送,其他节点在此时只能接收

8.1.2 协议层

位时序

意义:为了实现正确的总线电平采样,确保通讯正常。最小单位是Tq(Time Quantum),一个完整位由8~25个Tq组成

组成:SS段、PTS 段、PBS1段、PBS2段

段名意义作用
SS(1Tq)同步段使总线各节点同步
PTS(1~8Tq)传播时间段补偿物理延时,是传播时间、收发器延时之和的两倍
PBS1(1~8Tq)相位缓冲段1补偿变压阶段误差
PBS2(2~8Tq)相位缓冲段2补偿边沿阶段误差
SJW(1~4Tq)再同步补偿宽度补偿时钟频率偏差、传输延迟等

例如

在这里插入图片描述

通讯波特率的计算:CAN使用的时钟线是APB1 peripheral clocks(假设是APC),即一般是SYSCLK的四分频。而CAN通讯还要对此进行预分频(假设是Prescaler),则一个Tq为 Prescaler / APC(单位s)。而一个数据位占(SS+PTS+PBS1+PBS2+SJW)个Tq。则一秒可以传输的位数就是 1 T q ∗ 一 个 位 得 T q 数 \frac{1}{Tq*一个位得Tq数} TqTq1

例如:在时钟树查得APB1 peripheral clocks是45MHz,预分频为5,则一个Tq为 4 45 M H z = 111.1111 … ( n s ) \frac{4}{45MHz}=111.1111\dots(ns) 45MHz4=111.1111(ns) ,上图中有19个Tq,则此时波特率为 1 19 ∗ 111.11 ∗ 1 0 − 9 ≈ 473689 ( b p s ) \frac{1}{19*111.11*10^{-9}}\approx473689(bps) 19111.111091473689(bps)

报文

帧类型:

类型用途
数据帧发送单元向接收单元信息内容
遥控帧接收单元发送单元请求数据
错误帧通知其他单元检测到错误
过载帧通知还没有准备好接收
间隔帧将数据帧或遥控帧前面的帧隔开

数据帧结构:

以一个显性位(0)开始,以一个7个连续隐形位(1)结束。中间依次是仲裁段、控制段、数据段、CRC段、ACK段,一共7段

在这里插入图片描述

帧起始(SOF):一个显性电平。用于通知各个节点将有数据传输

仲裁段:用于表示优先级。标准格式和扩展格式得区别就是在这里,标准格式ID为11位,扩展格式为11+18=29位。RTR(远程传输请求位),用显隐性电平区别数据帧和遥控帧。

​ IDR(标识符扩展位),显性是标准形式,隐性是扩展形式。

​ SSR,即标准格式的RTR,是隐性位。

​ ID决定数据帧的优先级,当两个节点同时竞争总线,则先出现隐性电平的节点失去占有权,进入接收状态

控制段:r1和r0是保留位,默认显性。DLC,数据数组长度,0~8

数据段:08个字节(064位)

CRC段:共16位。15位的CRC校验码,1位的界定符,隐性

ACK段:共2位。一位是ACK槽位,发送端发送隐性,接收端发送显性表示应答;一位是与帧结束的界定符

帧结束(ROF):7个隐形位

8.1.3 过滤器

目的:过滤掉不感兴趣的消息,即与本节点无关的消息

两种模式:列表模式和掩码模式

过滤器个数:使用一个CAN时可选013号过滤器;使用两个CAN是,可选用037号过滤器

模式

列表模式:将关注的报文ID做成一张表,当收到的报文ID符合时则接收,否则不接收

优点,精确,能完全过滤掉不需要的报文

缺点,列表数量有限,当感兴趣的消息数量过多时则无法全部包含

掩码模式通过与操作,将部分ID符合的报文接收

优点,感兴趣的范围可以更大

缺点,并不一定能完全过滤掉不关注的报文,精确程度取决于屏蔽码

位宽

过滤器有32位和16位两种可选。其中16位只能过滤标准帧,不能过滤扩展帧。

8.2 STM32的CAN

STM32有两组CAN控制器,CAN1是主设备,负责管理bxCAN(基本扩展CAN,就是CAN)和512字节的SRAM。CAN2是从控制器,不能直接访问SRAM。使用CAN2必须使能CAN1外设时钟

STM32中,当CAN接收过滤器使用32位时,掩码和验证码分别拆分成两个寄存器,每个16位,分别代表高16位和低16位

8.3 CubeMX配置步骤

  1. 左侧目录>Connectivity>点CAN1/CAN2~> Mode勾选Master Mode / Slave Mode

  2. 配置参数,含义如下:
    在这里插入图片描述

    参数意思
    Prescaler预分频,即位时序提到的APB1 peripheral clocks继续分一次频
    Time Quantum最小时间单位Tq,自动计算出来的,不需要填写
    Time Quanta in Bit Segment 1PBS1段长度
    Time Quanta in Bit Segment 2PBS2段长度
    ReSynchronization Jump Width重同步跳跃宽度,即位时序提到的SJW
    Time Triggered Communication Mode是否使能时间触发
    Automatic Bus-Off Management是否使能自动离线管理
    Automatic Wake-Up Mode是否使能自动唤醒
    Qutomatic Retransmission是否使能自动重传
    Receive Fifo Locked Mode是否使能锁定FIFO
    Transmit Fifo Priority配置报文优先级的判断方法
    Oprating Mode操作模式

    这些参数也可以在can.c中自行修改

  3. 中断(NVIC)设置,根据需要设置,一般勾上CAN1 RX0 Interrupt

8.4 编程

HAL库关于CAN的所有函数定义和结构体定义分别在 Drivers/STM32F4xx_HAL_Driver 文件夹下 stm32f4xx_hal_can.c 和 stm32f4xx_hal_spi.h 中

下面列举一些基本的和常用的

8.4.1 CAN基本结构体

发送报文定义结构体(CAN_TxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;    /*!标准ID。参数值只能是 0 到 0x7FF(二进制的11位1) */

  uint32_t ExtId;    /*!扩展ID。参数值只能是 0 到 0x1FFFFFFF(二进制的29位1)*/

  uint32_t IDE;      /*!IDE。HAL库编程时,标准帧填写CAN_ID_STD,扩展帧填写CAN_ID_EXT */

  uint32_t RTR;      /*!RTR。HAL库编程时,数据帧填写CAN_RTR_DATA,遥控帧填写CAN_RTR_REMOTE */

  uint32_t DLC;      /*!DLC。数据长度,参数值只能是 0 到 8 */

  FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
                          of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
                          @note: Time Triggered Communication Mode must be enabled.
                          @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
                          This parameter can be set to ENABLE or DISABLE. */

} CAN_TxHeaderTypeDef;

接收报文定义结构体(CAN_RxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;   

  uint32_t ExtId;    

  uint32_t IDE;      

  uint32_t RTR;      

  uint32_t DLC;      

  uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception.
                          @note: Time Triggered Communication Mode must be enabled.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */

  uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */

} CAN_RxHeaderTypeDef;

接收过滤器类型定义结构体(CAN_FilterTypeDef)

typedef struct
{
  uint32_t FilterIdHigh;          /*!过滤器验证码ID高16位,只能填0到0xFFFF 中间的数值 */

  uint32_t FilterIdLow;           /*!过滤器ID低16位,只能填0到0xFFFF 中间的数值*/

  uint32_t FilterMaskIdHigh;      /*!过滤器掩码ID高16位,只能填0到0xFFFF中间的数值 */

  uint32_t FilterMaskIdLow;       /*!过滤器掩码ID低16位,只能填0到0xFFFF中间的数值 */

  uint32_t FilterFIF(x)Assignment;  /*!将通过的报文放入哪个FIFOx中,填写FIFO(x) */

  uint32_t FilterBank;            /*!使用过滤器编号。使用一个CAN,则可选 0~13;使用两个CAN可选                                        0~27 */

  uint32_t FilterMode;            /*!过滤器模式选择。掩码模式填写 CAN_FILTERMODE_IDMASK,列表模
                                     式填写 CAN_FILTERMODE_IDLIST */

  uint32_t FilterScale;           /*!过滤器位宽,32位是CAN_FILTERSCALE_32BIT,
                                               16位是CAN_FILTERSCALE_16BIT */

  uint32_t FilterActivation;      /*!是否使能过滤器,DISABLE 或 ENABLE */

  uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
                                       For single CAN instances, this parameter is meaningless.
                                       For dual CAN instances, all filter banks with lower index are assigned to master
                                       CAN instance, whereas all filter banks with greater index are assigned to slave
                                       CAN instance.
                                       This parameter must be a number between Min_Data = 0 and Max_Data = 27. */

} CAN_FilterTypeDef;

注意:FilterIdHigh、FilterIdLow、FilterMaskIdLow、FilterMaskIdLow这四个成员不是它的名字那么简单,

​ 他们的功能取决于使用的过滤器模式。若为列表模式,则不管是FilterId还是FilterMaskId都表示的是列

​ 表成员。

​ 上述四个成员都是16位的,一定注意下面说的移位操作

​ 在32位过滤器中,一组High和Low检验同一个CAN ID;16位过滤器,则可分别独立检验一个ID

过滤器寄存器如下:(使用HAL库可以不必深挖具体的寄存器,只需注意Mapping每一位的内容)

​ 32位列表模式

在这里插入图片描述

​ 16位列表模式

在这里插入图片描述
​ 32位掩码模式
16位掩码模式
在这里插入图片描述

标准帧用16位过滤器表示:FilterIdHigh、FilterIdLow、FilterMaskIdLow、FilterMaskIdLow各可以表示一个列表成员。由于标准帧的ID是11位的,所以需要将其ID左移5位

标准帧用32位过滤器表示:FilterIdHigh、FilterIdLow共同表示一个ID,FilterMaskIdLow、FilterMaskIdLow共同表示一个ID。由于标准帧ID是11位的,故表示时其ID需左移5位存入High,且LOW = 0 | CAN_ID_STD (意思是将IDE位置为0)

扩展帧用32位过滤器表示:扩展帧的ID是29位的,所以将扩展帧ID先左移3位与32位按高位对齐,再右移16位并取低16位,存入High;将扩展帧ID左移3位与32位对齐,再取低16位存入Low。具体操作如下

CAN_FilterTypeDef sFilterConfig                                 //定义过滤器设置结构体变量
uint32_t StdId =0x321;				                            //一个标准CAN ID
uint32_t ExtId =0x1800f001;			                            //一个扩展CAN ID

sFilterConfig.FilterIdHigh = StdId<<5;			                //标准ID放入FilterIdHigh
sFilterConfig.FilterIdLow = 0|CAN_ID_STD;			            //标准ID,故设置IDE位为0

sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;       //扩展帧ID高16位放入                                                                           FilterMaskIdHigh
sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;	//扩展帧ID高16位放入                                                                           FilterMaskIdLow,并设置                                                                     IDE位为1

关于验证码和掩码:假设有一个关注列表,里面全是感兴趣的报文。验证码可以是关注列表中任意一个成员的ID(经上述处理),而掩码是所有感兴趣的成员的同或的结果

在这里插入图片描述

综上,两种位宽,两种模式,共四种过滤模式,特点总结如下:

模式特点
16位列表可包含四个列表成员
32位列表可包含两个列表成员
16位掩码可检验两对验证码和掩码
32位掩码可检验一对验证码和掩码

8.4.2 CAN 基本函数

控制函数如下表

函数功能
HAL_CAN_Start开启CAN通讯
HAL_CAN_Stop关闭CAN通讯
HAL_CAN_RequestSleep尝试进入休眠模式
HAL_CAN_WakeUp从休眠模式中唤醒
HAL_CAN_IsSleepActive检查是否成功进入休眠模式
HAL_CAN_AddTxMessage向 Tx 邮箱中增加一个消息,并且激活对应的传输请求
HAL_CAN_AbortTxRequest请求中断传输
HAL_CAN_GetTxMailboxesFreeLevelReturn Tx mailboxes free level
HAL_CAN_IsTxMessagePending检查是否有传输请求在指定的 Tx 邮箱上等待
HAL_CAN_GetRxMessage从Rx FIFO 收取一个 CAN 帧
HAL_CAN_GetRxFifoFillLevelReturn Rx FIFO fill level
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)**

功能:开启CAN,一般一开始就要打开
参数:CAN句柄指针,&hcan1 或 &hcan2
返回值:返回值:HAL状态

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

功能:配置CAN过滤器
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,CAN配置结构体的指针
返回值:返回值:HAL状态

HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)

功能:使能中断
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,使能哪个中断,在stm32f4xx_HAL_Driver.h中,搜索Receive Interrupts可以查到各宏定义
返回值:返回值:HAL状态

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)(根据使用0可能替换成1

功能:接收回调函数,CAN回调后进行的操作。一般在此接收数据
参数:第一个,CAN句柄指针
返回值:void

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

功能:增加一个消息到第一个空闲的 Tx 邮箱,并且激活对应的传输请求

参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,发送报文定义结构体的指针
​ 第三个,数据帧数组的内容,长度不能超过定义的长度
​ 第四个,Tx邮箱,可填 (uint32_t*)CAN_TX_MAILBOX0 ,CAN_TX_MAILBOX1 , CAN_TX_MAILBOX3
返回值:HAL状态

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

功能:从Rx FIFO收取一个 CAN 帧
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2​
第二个,Rx FIFO,可填 CAN_RX_FIFO0, CAN_RX_FIFO1
​ 第三个,接收报文定义结构体的指针
​ 第四个,接受数据数组
返回值:HAL状态

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

功能:设置接收过滤器
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,过滤器类型定义结构体指针
返回值:HAL状态

8.4.3 CAN编程步骤示例

  1. 定义接收过滤器类型定义结构体(CAN_FilterTypeDef)变量

  2. 配置CAN接收过滤器HAL_CAN_ConfigFilter

  3. 开启CAN,HAL_CAN_Start

  4. 发送,HAL_CAN_AddTxMessage

  5. 接收,需要先开启中断HAL_CAN_ActivateNotification,第二个参数设置为CAN_IT_RX_FIFO0_MSG_PENDING

    接收中断回调函数HAL_CAN_RxFifo0MsgPendingCallback,里面定义接收报文定义结构体(CAN_RxHeaderTypeDef)结构体变量。用接收函数HAL_CAN_GetRxMessage接收

  • 102
    点赞
  • 431
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 钉钉自动打卡是一种利用钉钉应用程序上的自动定位和打卡功能来实现自动打卡记录的方法。在钉钉应用中,可以使用定位功能获取当前的地理位置信息,并且可以设置在特定时间自动进行打卡操作。 钉钉自动打卡的实现主要分为两个步骤。首先,用户需要在钉钉应用中设置打卡位置和打卡时间。可以通过搜索公司名称或者手动输入公司地址来设定打卡位置,在打卡时间中选择需要自动打卡的时间段。接下来,钉钉应用会在设定的时间段内自动定位当前位置,并且根据定位结果自动进行打卡操作。 钉钉自动打卡的好处是可以节省时间和精力。对于需要频繁打卡的人员来说,手动打卡可能会造成时间和精力的浪费。而使用钉钉自动打卡功能,只需要事先设定好打卡位置和时间,之后就可以自动进行打卡,大大提高了工作效率。 钉钉自动打卡也有一些注意事项。首先,需要确保设备开启了定位功能,否则无法获取到准确的地理位置信息。其次,打卡位置需要在公司内,否则系统会进行提醒或报警。另外,用户也可以选择手动打卡,以应对特殊情况。 总而言之,钉钉自动打卡是一种利用钉钉应用上的定位和打卡功能实现自动化打卡记录的方法。它可以节省时间和精力,提高工作效率,但需要注意一些细节,以确保打卡的准确性和可靠性。 ### 回答2: dingding-automatic-clock-in是一款用于自动打卡的手机应用。它是为了满足企业和员工打卡需求而开发的工具。 该应用通过与钉钉打卡系统的对接,可以实现自动定时打卡的功能。员工只需在应用中设置每天的上班和下班时间,以及打卡地点的范围,应用就会自动按照设定的时间和位置进行定时打卡。 这款应用的好处有很多。首先,它节省了员工手动打卡的时间和精力。员工不再需要每天上班或下班时专门打开钉钉应用进行打卡,而是通过设置好打卡时间,应用会自动帮助员工完成打卡流程。 其次,dingding-automatic-clock-in还提高了打卡的准确性和可靠性。由于是自动打卡,避免了员工忘记打卡或漏打卡的情况发生。同时,应用内置GPS定位功能,确保员工在规定范围内进行打卡,防止打卡地点的虚假报告。 再次,应用也有助于公司的管理和数据统计。公司可以根据员工的打卡记录,准确统计员工的上班和下班时间,以及出勤情况。这有助于企业管理者更好地了解员工的工作状况,进行工时和考勤的管理。 总体来说,dingding-automatic-clock-in为企业和员工提供了一个方便、准确并且可靠的自动打卡解决方案。它的使用能够提高员工打卡的效率和准确性,同时也提供了对考勤数据的详细统计,进一步提高了企业的管理水平。 ### 回答3: 钉钉自动打卡是一种通过钉钉APP实现自动打卡的方法。在一些公司和组织中,为了管理员工的考勤情况,通常需要每天上班和下班时进行打卡操作。然而,对于一些员工来说,每天都要手动打卡是一种繁琐的任务。 钉钉自动打卡可以通过一些脚本或软件来实现。这些脚本或软件会在指定的时间自动登录到钉钉APP,完成打卡操作,从而实现自动打卡的目的。 使用钉钉自动打卡的好处是可以帮助减轻员工的负担,提高效率。员工不再需要每天都手动打卡,只需要确保手机处于待机状态,并设置好打卡的时间和地点,钉钉自动打卡就能完成。这样,员工可以将更多的注意力放在工作上,减少了繁琐的打卡操作。 然而,钉钉自动打卡也存在一些问题。首先,需要在手机上安装非官方的脚本或软件,可能存在安全风险。其次,如果设置不当或者网络出现问题,可能会导致打卡失败或记录不准确。因此,使用钉钉自动打卡需要慎重考虑,并遵循公司相关政策和规定。 在总结中,钉钉自动打卡提供了一种更便捷的打卡方式,可以减轻员工的负担,提高效率。然而,使用之前需要了解相关的风险和政策要求,在合适的情况下进行使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值