CAN笔记(15) STM32-M4 CAN通讯

本文详细介绍了在STM32-M4上配置和测试CAN通讯的过程,包括初始化配置、滤波器设置、发送和接收消息的实现。通过按键控制工作模式和数据发送,使用LCD模块显示接收到的数据。在正常和环回模式下进行测试,并提供了相关的硬件资源和软件配置步骤。
摘要由CSDN通过智能技术生成


1. 期望效果

通过 KEY1 按键选择 CAN 的工作模式(正常模式/环回模式)
通过 KEY0 按键控制数据发送(8个8位随机数)
通过查询的办法,将接收到的数据显示在 LCD 模块上

环回模式下,用一个最小系统板即可测试
正常模式下,需要 2 个拥有 CAN接口的最小系统板,并且将其对接起来
用 2 根导线将两个 CAN 端子的 CAN_LCAN_LCAN_HCAN_H 连接起来
然后一个最小系统板发送数据,另外一个最小系统板将接收到的数据显示在 LCD 模块上


2. 硬件资源

除了F429最小系统板的基本硬件配置,还需要以下硬件资源:

  1. 指示灯 LED0
  2. 按键 KEY0 和 KEY1
  3. LCD 模块(如果没有屏幕显示模块,也可以采用串口通讯进行交互)
  4. CAN 收发芯片 JTA1050
    在这里插入图片描述

3. 初始化配置

创建一个CANTest1工程,包含了基础的 HAL
CAN相关的函数在文件 stm32f4xx_hal_can.c 和 对应的头文件stm32f4xx_hal_can.h


3.1. 配置相关引脚

第一步就要使能 CAN 的时钟, CAN 的时钟通过 APB1ENR 的第 25 位来设置
其次要设置 CAN 的相关引脚为复用输出
这里需要设置 PA11(CAN1_RX)和 PA12(CAN1_TX)为复用功能( AF9)
并使能 PA 口的时钟

这里创建一个CAN底层驱动函数HAL_CAN_MspInit,进行所述的配置

具体配置过程如下:

void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
   
	GPIO_InitTypeDef GPIO_Initure;

	__HAL_RCC_CAN1_CLK_ENABLE();					//使能CAN1时钟
	__HAL_RCC_GPIOA_CLK_ENABLE();					//开启GPIOA时钟

	GPIO_Initure.Pin = GPIO_PIN_11 | GPIO_PIN_12;   //PA11,12
	GPIO_Initure.Mode = GPIO_MODE_AF_PP;			//推挽复用
	GPIO_Initure.Pull = GPIO_PULLUP;				//上拉
	GPIO_Initure.Speed = GPIO_SPEED_FAST;			//快速
	GPIO_Initure.Alternate = GPIO_AF9_CAN1;			//复用为CAN1
	HAL_GPIO_Init(GPIOA, &GPIO_Initure);			//初始化
}

3.2. 设置 CAN 工作模式及波特率等

这一步通过先设置 CAN_MCR 寄存器的 INRQ 位,让 CAN 进入初始化模式
然后设置CAN_MCR 的其他相关控制位

再通过 CAN_BTR 设置波特率和工作模式(正常模式/环回模式)等信息
最后设置 INRQ 为 0,退出初始化模式

在库函数中,提供了函数 HAL_CAN_Init 用来初始化 CAN 的工作模式以及波特率
HAL_CAN_Init 函数体中,就会进行上述的配置
所以在调用这个函数的前后不需要再进行初始化模式设置
下面来看看 HAL_CAN_Init 函数的声明:

HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan);

该函数入口参数只有 hcan 一个,为 CAN_HandleTypeDef 结构体指针类型

结构体 CAN_HandleTypeDef 定义:

typedef struct
{
   
  CAN_TypeDef                 *Instance;  /*!< Register base address          */
  CAN_InitTypeDef             Init;       /*!< CAN required parameters        */
  CanTxMsgTypeDef*            pTxMsg;     /*!< Pointer to transmit structure  */
  CanRxMsgTypeDef*            pRxMsg;     /*!< Pointer to reception structure */
  __IO HAL_CAN_StateTypeDef   State;      /*!< CAN communication state        */
  HAL_LockTypeDef             Lock;       /*!< CAN locking object             */
  __IO uint32_t               ErrorCode;  /*!< CAN Error code                 */
}CAN_HandleTypeDef;

该结构体除了 StateLock ,和 ErrorCode 三个 HAL 库处理状态过程变量之外
只有四个成员变量需要外部设置:

  1. Instance 位寄存器基地址
    这里使用 CAN1,设置为 CAN1 即可

  2. Init 参数初始化配置
    它是 CAN_InitTypeDef 结构体类型,该结构体定义为:

    typedef struct
    {
         
      uint32_t Prescaler;	//波特率分频器
      uint32_t Mode;		//模式
      uint32_t SJW;			//重新同步跳跃宽度
      uint32_t BS1;			//时间段 1 占用的时间单元数
      uint32_t BS2;			//时间段 2 占用的时间单元数
      uint32_t TTCM;		//时间触发通信模式
      uint32_t ABOM;		//自动的总线关闭管理
      uint32_t AWUM; 		//自动唤醒模式 
      uint32_t NART;		//禁止自动重发送
      uint32_t RFLM;		//接收 FIFO 锁定模式
      uint32_t TXFP;		//发送 FIFO 优先级
    }CAN_InitTypeDef;
    

    前面 5 个参数用来设置寄存器 CAN_BTR,用来设置模式以及波特率相关的参数
    后面 6 个参数用来设置寄存器 CAN_MCR,用来设置 CAN 通信相关的控制位

  3. pTxMsg 发送消息结构体指针
    在初始化 CAN 的时候要指定其指向
    那么后面调用发送函数 HAL_CAN_Transmit 之前,就可以通过 pTxMsg 指定发送数据和参数

  4. pRxMsg 接收消息结构体指针
    在初始化 CAN 的时候要指定其指向
    那么后面调用接收函数 HAL_CAN_Receive 之后,就可以通过 pRxMsg 获取接收数据和参数

这里创建一个CAN1初始化函数CAN1_Mode_Init,进行所述的配置
具体配置过程如下:

CAN_HandleTypeDef   CAN1_Handler;   //CAN1句柄
CanTxMsgTypeDef     TxMessage;      //发送消息
CanRxMsgTypeDef     RxMessage;      //接收消息

u8 CAN1_Mode_Init(u32 tsjw, u32 tbs2, u32 tbs1, u16 brp, u32 mode)
{
   
	CAN1_Handler.Instance = CAN1;		//寄存器基地址
	CAN1_Handler.pTxMsg = &TxMessage;	//发送消息
	CAN1_Handler.pRxMsg = &RxMessage;	//接收消息
	CAN1_Handler.Init.Prescaler = brp;	//分频系数(Fdiv)为brp+1
	CAN1_Handler.Init.Mode = mode;		//模式设置 
	CAN1_Handler.Init.SJW = tsjw;		//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位(CAN_SJW_1TQ~CAN_SJW_4TQ)
	CAN1_Handler.Init.BS1 = tbs1;		//tbs1范围(CAN_BS1_1TQ~CAN_BS1_16TQ)
	CAN1_Handler.Init.BS2 = tbs2;		//tbs2范围(CAN_BS2_1TQ~CAN_BS2_8TQ)
	CAN1_Handler.Init.TTCM = DISABLE;	//非时间触发通信模式 
	CAN1_Handler.Init.ABOM = DISABLE;	//软件自动离线管理
	CAN1_Handler.Init.AWUM = DISABLE;	//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN1_Handler.Init.NART = ENABLE;	//禁止报文自动传送 
	CAN1_Handler.Init.RFLM = DISABLE;	//报文不锁定,新的覆盖旧的 
	CAN1_Handler.Init.TXFP = DISABLE;	//优先级由报文标识符决定 

	if (HAL_CAN_Init(&CAN1_Handler) != HAL_OK) return 1;	//初始化
}

其中HAL_CAN_Init函数会调用HAL_CAN_MspInitCAN底层驱动函数


3.3. 设置滤波器

将使用滤波器组 0,并工作在 32 位标识符屏蔽位模式下
先设置 CAN_FMRFINIT 位,让过滤器组工作在初始化模式下
然后设置滤波器组 0 的工作模式以及标识符 ID和屏蔽位
最后激活滤波器,并退出滤波器初始化模式

在 HAL 库中,提供了函数 HAL_CAN_ConfigFilter 用来初始化 CAN 的滤波器相关参数
HAL_CAN_ConfigFilter 函数体中,就会进行上述的配置

HAL_CAN_ConfigFilter 函数的声明:

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)

该函数有 2 个入口参数:
第一个入口参数 hcan ,已经说明过了
第二个入口参数 sFilterConfigCAN_FilterConfTypeDef 结构体指针类型,用来设置滤波器相关参数

结构体 CAN_FilterConfTypeDef 定义为:

typedef struct
{
   
  uint32_t FilterIdHigh;		//过滤器的 32 位 ID<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氢键H-H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值