STM32CubeMX 下载和安装 详细教程
【HAL库】STM32CubeMX开发----STM32F407----目录
前言
本次实验以 STM32F407VET6 芯片为MCU,使用 25MHz 外部时钟源。
CAN通信波特率为 500K bps。
CAN通信引脚 与 MCU引脚 对应关系如下:
CAN通信引脚 | MCU引脚 |
---|---|
TX | PB9 |
RX | PB8 |
一、使用STM32CubeMX----新建CAN通信工程
步骤1:打开 STM32CubeMX 软件
具体 STM32CubeMX 界面如下:
步骤2:选择 从MCU开始我的项目
步骤3:选择MCU芯片
我们本次实验选择 STM32F407VET6 芯片做 MCU。
进入工程编辑,具体界面如下:
步骤4:设置烧写方式为 SWD模式
这一步必须选择一种烧写方式,否则烧写一次程序后,芯片中就没法再次烧写程序了。需要硬件重启才可以重新烧写程序。
STM32烧写程序连接方式详解
步骤5:设置时钟源
设置外部晶振为芯片系统时钟源。
步骤6:设置时钟
STM32F407 时钟最大频率为 168M
步骤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为通信引脚。
具体操作如下:
鼠标左键点击引脚,选择CAN通信功能。
最后结果如下:
2.配置参数
本次实验的APB1时钟频率 = 42MHz,在 步骤6设置时钟 中有介绍。
CAN波特率 = APB1时钟频率 / Prescaler / (1 + BS1 + BS2)
CAN波特率 | APB1时钟频率 | Prescaler | BS1 | BS2 |
---|---|---|---|---|
500KBPS | 42MHz | 7 | 9 | 2 |
具体操作如下:
3. 中断配置
勾选CAN通信接收中断RX0
步骤8:项目编辑
步骤9:代码生成编辑
步骤10:点击 GENERATE CODE 生成代码
新建的工程,已经生成,接下来就是对工程代码的编辑。
二、使用keil5----编辑程序
想要使用keil5打开工程,需要电脑先安装 keil5编译环境,具体操作流程。
可以点击下方文章链接:Keil5编译环境搭建流程
1. CAN相关HAL库函数说明
//开启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);
//向 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);
//从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);
2. CAN通信配置流程
STM32CubeMX生成CAN通信工程程序后,还需要做以下配置,才能实现CAN收发功能。
(1)配置过滤器
(2)启动CAN外围设备
(3)激活CAN接收中断
具体程序如下:
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();
}
}
3. CAN通信----发送
CAN总线通信发送配置流程
- 写入标识符
- 写入标识符类型(标准帧/扩展帧)
- 写入帧类型(远程帧/数据帧)
- 写入数据长度
- 写入数据
- 发送数据
具体程序如下:
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总线通信接收配置流程
- 进入CAN总线接收中断回调函数
- 从Rx FIFO区域获取数据
- 解析接收数据
- 实现对应功能
具体代码如下:
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();
}
/*
处理接收到的数据
*/
}