关于CAN通信的入门教程和基本原理在其他博主发的文章里面都有介绍,笔者只是简单记录下学习过程,文章用到的是正点原子的阿波罗F429开发板,另一个设备是中盛科技的继电器模块(CAN版)。
实现之前看一下继电器模块相关信息
发送数据的格式官方文档已经给与说明,帧ID的格式就是功能码+地址码,地址码默认是0x01,例如想让继电器由闭合转为断开状态,只需要向继电器模块发送0x0101(写继电器状态功能码+默认地址码) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00即可。
然后打开Cube开始简单配置
1.CAN功能引脚选择PA11,PA12(对照开发板原理图),因为继电器模块默认波特率是250kbps,所以配置的一定要把波特率配好。时钟配置就默认流程
另外配置了按键和LED作为提示
代码部分:
can.c
void MX_CAN1_Init(void)
{
/* USER CODE BEGIN CAN1_Init 0 */
/* USER CODE END CAN1_Init 0 */
/* USER CODE BEGIN CAN1_Init 1 */
/* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 36;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN1_Init 2 */
CAN_FilterTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.FilterBank = 0;
CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInitStructure.FilterIdHigh = 0x0000;
CAN_FilterInitStructure.FilterIdLow = 0x0000;
CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FilterFIFO0;
CAN_FilterInitStructure.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan1,&CAN_FilterInitStructure);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE END CAN1_Init 2 */
}
因为Cube并不会帮我们生成筛选器配置的相关代码,所以我们要在初始化-用户代码区域自己添加代码
main.c
/*CAN发送*/
void CAN_SEND(void)
{
CAN_TxHeaderTypeDef CAN_TX;
uint32_t TX_MAILBOX;
uint8_t TX_DATA[8] = {0x03,0x00,0x00,0x00,0x00,0xf0,0x00,0x00};//继电器模块
//手册有说明,该段表示1-2号继电器得电,45-48号继电器得电。
CAN_TX.DLC = 8;
CAN_TX.ExtId = 0x0000;
CAN_TX.StdId = 0x0101;//标准帧ID
CAN_TX.IDE = CAN_ID_STD;//标准帧
CAN_TX.RTR = CAN_RTR_DATA;//数据帧
CAN_TX.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1,&CAN_TX,TX_DATA,&TX_MAILBOX);
}
/*CAN接收*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
CAN_RxHeaderTypeDef RxMessage;
uint8_t Data[2];
RxMessage.DLC = 2;
RxMessage.StdId = 0x00;
RxMessage.ExtId = 0x0000;
RxMessage.IDE=CAN_ID_EXT;
RxMessage.RTR=CAN_RTR_DATA;
if (HAL_CAN_GetState(hcan1)!= RESET)
{
HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, Data);
if (Data[0] == 0x99)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
//第一位数据是0x99,LED灭
}
if(Data[1] == 0x99)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
//第二位数据是0x99,LED亮
}
}
}
不需要写在大循环里,每次发送按下复位就行。
因为只需要控制继电器模块,所以按照使用手册来修改或添加发送的数据就行了。文章来源:https://www.toymoban.com/news/detail-592235.html
本文只用于记录,工程文档不一定具有参考意义。文章来源地址https://www.toymoban.com/news/detail-592235.html
到了这里,关于STM32+Cube mx hal库实现CAN通信收发实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!