can通信基础知识参考:
STM32的can直接查阅数据手册。
关键代码
/* Includes ------------------------------------------------------------------*/ #include "MyApplication.h" /* Private define-------------------------------------------------------------*/ /* Private variables----------------------------------------------------------*/ /* Private function prototypes------------------------------------------------*/ static void CAN_Init(void); //初始化 static void CAN_Config(void); //配置 static uint8_t CAN_Send_Msg(uint8_t*, uint8_t); //发送信息 static uint8_t CAN_Rec_Msg(uint8_t*); //接收信息 /* Public variables-----------------------------------------------------------*/ CAN_TEST_t CAN_TEST = { CAN_MODE_LOOPBACK, CAN_Init, CAN_Config, {0}, {0}, CAN_Send_Msg, CAN_Rec_Msg, FALSE }; /* Private function prototypes------------------------------------------------*/ /* * @name CAN_Init * @brief CAN初始化 * @param None * @retval None */ static void CAN_Init() { } /* * @name CAN_Config * @brief CAN配置 * @param None * @retval None */ static void CAN_Config() { CAN_FilterTypeDef CAN_Filter; //设定CAN过滤器参数 CAN_Filter.FilterBank = 0; //配置过滤器0(STM32F1共14个,0-13) CAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT; //16位过滤器 CAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK; //标识符屏蔽模式 CAN_Filter.FilterIdLow = 0x00; //FR1 CAN_Filter.FilterMaskIdLow = 0x00; CAN_Filter.FilterIdHigh = 0x00; //FR2 CAN_Filter.FilterMaskIdHigh = 0x00; CAN_Filter.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0 CAN_Filter.FilterActivation = ENABLE; //激活过滤器0 CAN_Filter.SlaveStartFilterBank = 14; //配置过滤器 if(HAL_CAN_ConfigFilter(&hcan, &CAN_Filter) != HAL_OK) { printf("CAN配置函数:配置过滤器!"); System.Error_Handler(); } //使能FIFO0接收到一个新报文中断 if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { printf("CAN配置函数:使能FIFO0接收到一个新报文中断!"); System.Error_Handler(); } //启动CAN if(HAL_CAN_Start(&hcan) != HAL_OK) { printf("CAN配置函数错误:CAN启动失败!"); System.Error_Handler(); } printf("配置成功,并成功启动CAN\r\n"); } /* * @name CAN_Send_Msg * @brief CAN发送信息 * @param pSend_Buf -> 发送缓存指针 * LEN -> 发送长度 * @retval CAN_Send_ok -> 发送成功 CAN_Send_fail -> 发送失败 */ static uint8_t CAN_Send_Msg(uint8_t* pSend_Buf, uint8_t LEN) { uint8_t i = 0; static uint8_t ucTestData = 0; uint32_t TxMailBox; //接收CAN发送成功时返回的邮箱号(0-2) //定义CAN Tx消息头参数 CAN_TxHeaderTypeDef CAN_TxHeader = { 0x88, //标准标识符 - 11位 0x00, //扩展标识符 - 29位 CAN_ID_STD, //使标准帧 CAN_RTR_DATA, //数据帧 8, //发送8位数据 - 范围0-8 DISABLE }; if(CAN_TEST.Operate_Mode == CAN_MODE_LOOPBACK) printf("CAN工作在环回模式 -> 只需1块实战板即可测试\r\n"); else printf("CAN工作在正常模式 -> 至少2块实战板方可测试\r\n"); //设定待发送数据 printf("CAN发送报文,数据如下:"); for(i=0;i<8;i++) { printf("0x%.2x,",ucTestData); CAN_TEST.Send_Buf[i] = ucTestData++; } printf("\r\n"); //将消息添加到第一个免费的Tx邮箱并激活相应的传输要求 if(HAL_CAN_AddTxMessage(&hcan, &CAN_TxHeader, pSend_Buf, &TxMailBox) != HAL_OK) { return CAN_Send_fail; } //通过检查空闲邮箱个数确认是否发送完成 Timer6.usDelay_Timer = 0; do { //超时处理 if(Timer6.usDelay_Timer >= TIMER6_1S) { printf("CAN发送超时\r\n"); return CAN_Send_fail; } } while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3); //发送成功 return CAN_Send_ok; } /* * @name CAN_Rec_Msg * @brief CAN接收信息 * @param pRec_Buf -> 接收缓存指针 * @retval CAN_Rec_ok -> 接收成功 CAN_Rec_fail -> 接收失败 */ static uint8_t CAN_Rec_Msg(uint8_t* pRec_Buf) { uint8_t i; printf("CAN接收到报文,数据如下:"); for(i=0;i<8;i++) printf("0x%.2x,",*(pRec_Buf+i)); printf("\r\n"); return CAN_Rec_ok; } /******************************************************** End Of File ********************************************************/