【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验

STM32CubeMX 下载和安装 详细教程
【HAL库】STM32CubeMX开发----STM32F407----目录

CAN通信----基本原理----详细介绍


前言

本次实验以 STM32F407VET6 芯片为MCU,使用 25MHz 外部时钟源。
CAN通信波特率为 500K bps。
CAN通信引脚MCU引脚 对应关系如下:

CAN通信引脚 MCU引脚
TX PB9
RX PB8

一、使用STM32CubeMX----新建CAN通信工程

步骤1:打开 STM32CubeMX 软件

具体 STM32CubeMX 界面如下:

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第1张图片

步骤2:选择 从MCU开始我的项目

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第2张图片

步骤3:选择MCU芯片

我们本次实验选择 STM32F407VET6 芯片做 MCU

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第3张图片

进入工程编辑,具体界面如下:

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第4张图片

步骤4:设置烧写方式为 SWD模式

这一步必须选择一种烧写方式,否则烧写一次程序后,芯片中就没法再次烧写程序了。需要硬件重启才可以重新烧写程序。

STM32烧写程序连接方式详解

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第5张图片

步骤5:设置时钟源

设置外部晶振为芯片系统时钟源。

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第6张图片

步骤6:设置时钟

STM32F407 时钟最大频率为 168M

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第7张图片

步骤7:CAN通信配置

1.选择引脚

CAN通信引脚选择如下表:

CAN引脚 MCU引脚1 MCU引脚2 MCU引脚3
CAN1_RX PA11 PB8 PD0
CAN1_TX PA12 PB9 PD1
CAN2_RX PB5 PB12 /
CAN2_TX PB6 PB13 /

我们这次选择:CAN1通信,PB8,PB9为通信引脚。
具体操作如下:

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第8张图片

鼠标左键点击引脚,选择CAN通信功能。

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第9张图片
【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第10张图片

最后结果如下:

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第11张图片

2.配置参数

本次实验的APB1时钟频率 = 42MHz,在 步骤6设置时钟 中有介绍。
CAN波特率 = APB1时钟频率 / Prescaler / (1 + BS1 + BS2)

CAN波特率 APB1时钟频率 Prescaler BS1 BS2
500KBPS 42MHz 7 9 2

具体操作如下:
【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第12张图片

3. 中断配置

勾选CAN通信接收中断RX0
【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第13张图片

步骤8:项目编辑

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第14张图片

步骤9:代码生成编辑

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第15张图片

步骤10:点击 GENERATE CODE 生成代码

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验_第16张图片
新建的工程,已经生成,接下来就是对工程代码的编辑。

二、使用keil5----编辑程序

想要使用keil5打开工程,需要电脑先安装 keil5编译环境,具体操作流程。
可以点击下方文章链接:Keil5编译环境搭建流程

HAL库反馈状态枚举

typedef enum 
{
  HAL_OK       = 0x00U,		//成功
  HAL_ERROR    = 0x01U,		//错误
  HAL_BUSY     = 0x02U,		//忙碌
  HAL_TIMEOUT  = 0x03U		//超时
} HAL_StatusTypeDef;

1. CAN通信----初始化

CAN总线通信----初始化配置流程

STM32CubeMX生成CAN通信工程程序后,还需要做以下配置,才能实现CAN收发功能。
(1)配置 CAN接收过滤器
(2)启动 CAN外围设备
(3)激活 CAN接收中断

相关HAL库函数

//配置CAN接收过滤器
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig);

//开启CAN通讯
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
//关闭CAN通讯	
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_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
//禁用CAN中断函数
HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs);
//CAN中断处理函数
void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan);

具体功能代码

void User_CAN1_Init(void)
{
 /*配置CAN过滤器*/
  CAN_FilterTypeDef FilterConfig;
 
  FilterConfig.FilterBank = 0;         //过滤器组号
  FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;	//过滤模式:屏蔽位模式--CAN_FILTERMODE_IDMASK,列表模式--CAN_FILTERMODE_IDLIST
  FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//过滤器位宽:32位
  FilterConfig.FilterIdHigh = 0x0000;               //32位ID
  FilterConfig.FilterIdLow = 0x0000;
  FilterConfig.FilterMaskIdHigh = 0x0000;           //32位MASK
  FilterConfig.FilterMaskIdLow = 0x0000;
  FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器0关联到FIFO0
  FilterConfig.FilterActivation = ENABLE;          //激活滤波器0
  FilterConfig.SlaveStartFilterBank = 14;		  //单CAN此参数无意义
  //过滤器配置
  if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  //启动CAN外围设备
  if(HAL_CAN_Start(&hcan1) != HAL_OK) 
  {
    Error_Handler();
  }
  //激活CAN接收中断
  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    Error_Handler();
  }
}

2. CAN通信----发送

CAN总线通信----发送配置流程

  1. 写入标识符
  2. 写入标识符类型标准帧/扩展帧
  3. 写入帧类型远程帧/数据帧
  4. 写入数据长度
  5. 写入数据
  6. 发送数据

相关HAL库函数

//向 Tx 邮箱中增加一个消息,并且激活对应的传输请求
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);	
//请求发送中断传输
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);	
//获取空闲Tx邮箱的数量
uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan);
//检查是否有传输请求在指定的 Tx 邮箱上等待
uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);	
//如果启用时间触发通信模式,则返回发送的Tx消息的时间戳。
uint32_t HAL_CAN_GetTxTimestamp(CAN_HandleTypeDef *hcan, uint32_t TxMailbox);

相关HAL库结构体

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 ~ 8

  FunctionalState TransmitGlobalTime; //必须启用时间触发通信模式,指定是否在DATA6和DATA7中发送帧传输开始时捕获的时间戳计数器值,以替换pData[6]和pData[7]。
  									  //DLC必须编程为8字节,以便发送这2个字节。此参数可设置为ENABLE(启用)或DISABLE(禁用)

} CAN_TxHeaderTypeDef;

具体功能代码

void CAN1_TX_Data(void)
{
	CAN_TxHeaderTypeDef	TxHeader;      
	uint8_t TX_data[8]={0,0,0,0,0,0,0,0};
	
	TxHeader.StdId = 0;					//标准标识符(11位)
	TxHeader.ExtId = 0x12345678; 		//扩展标识符(29位)
	TxHeader.IDE = CAN_ID_EXT ;			//扩展帧
	TxHeader.RTR = CAN_RTR_DATA;		//数据帧
	TxHeader.DLC = 8;				    //数据个数
	TxHeader.TransmitGlobalTime = DISABLE;
	
	TX_data[0] = 0x11;
	TX_data[1] = 0x22;
	TX_data[2] = 0x33;
	TX_data[3] = 0x44;
	TX_data[4] = 0x55;
	TX_data[5] = 0x66;
	TX_data[6] = 0x77;
	TX_data[7] = 0x88;
	
	uint32_t TxMailbox;
	
	HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TX_data, &TxMailbox);
}

4. CAN通信----接收

CAN总线通信----接收配置流程

  1. 进入CAN总线接收中断回调函数
  2. 从Rx FIFO区域获取数据
  3. 解析接收数据
  4. 实现对应功能

相关HAL库函数

//从Rx FIFO区域获取CAN帧到消息
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
//返回Rx FIFO填充水平
uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *hcan, uint32_t RxFifo);

//RX FIFO 0 消息回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);

相关HAL库结构体

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 ~ 8

  uint32_t Timestamp; //必须启用时间触发通信模式才可用,指定帧接收开始时捕获的时间戳计数器值。
  					  //取值范围:0 ~ 0xFFFF

  uint32_t FilterMatchIndex; //指定匹配接收筛选器元素的索引---取值范围:0 ~ 0xFF

} CAN_RxHeaderTypeDef;

具体功能代码

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle)
{
	CAN_RxHeaderTypeDef	RxHeader;     
	uint8_t RX_data[8]={0,0,0,0,0,0,0,0};
	 
	if(HAL_CAN_GetRxMessage(CanHandle, CAN_RX_FIFO0, &RxHeader, RX_data) != HAL_OK)
    {
      Error_Handler();
    }
	/*
	处理接收到的数据
	*/
}

你可能感兴趣的:(#,stm32,单片机,CAN,HAL库)