(這是一個最簡單的CAN示例Demo程序,僅作參考悔详。最新的HAL庫CAN的部分有所改變,不能直接使用該文方法惹挟,需要做簡單的修改茄螃。如有問題,歡迎留言连锯。)
STM32CubeMX版本:
固件庫版本:
第一步分:CubeMX軟件配置归苍。
0用狱、工程配置以及芯片選擇這里就不再贅述了。
1拼弃、打開CAN外設夏伊。
2、配置芯片時鐘樹吻氧。這里我使用了芯片內(nèi)部HSI RC溺忧。
3、CAN配置盯孙。
3.1配置波特率為1Mb/s鲁森。計算方法:42M/2/(14+6+1)==1M
3.2、使能接收中斷振惰。
到這里配置已經(jīng)完成了歌溉,這里我們只配置了部分選項,其余大部分都是采用的默認配置骑晶。點擊工具欄中齒輪圖標痛垛,生成代碼。
第二部分:代碼修改桶蛔。
1匙头、打開工程,打開can.c文件羽圃,在/* USER CODE BEGIN 0 */ ? 和?/* USER CODE END 0 */ 之間添加以下內(nèi)容乾胶。
#include?"main.h" ?
#define?F407VET6_BOARD_CAN_ID?????????0x001??
#define?SENSOR_BOARD_CAN_ID???????????0x002??
#define?ANOTHER_SENSOR_BOARD_CAN_ID???????0x003??
#define?THIRD_SENSOR_BOARD_CAN_ID?????0x004 ?
//2個3級深度的FIFO??
#define???CAN1FIFO???CAN_RX_FIFO0????????????????
#define???CAN2FIFO???CAN_RX_FIFO1??//???
CAN_TxHeaderTypeDef?????TxMeg;??
CAN_RxHeaderTypeDef?????RxMeg; ?
void?CAN_User_Init(CAN_HandleTypeDef*?hcan?)???//用戶初始化函數(shù)??
{??
?CAN_FilterTypeDef??sFilterConfig;??
?HAL_StatusTypeDef??HAL_Status; ?
??TxMeg.IDE=CAN_ID_STD;//CAN_ID_EXT;??
??TxMeg.RTR=CAN_RTR_DATA; ?
sFilterConfig.FilterBank?=?0;???????????????????????//過濾器0??
sFilterConfig.FilterMode?=??CAN_FILTERMODE_IDLIST;??//設為列表模式??????
sFilterConfig.FilterScale?=?CAN_FILTERSCALE_16BIT; ? ? ?
sFilterConfig.FilterIdHigh?=?F407VET6_BOARD_CAN_ID<<5;???//基本ID放入到STID中????
sFilterConfig.FilterIdLow??=?SENSOR_BOARD_CAN_ID?<<5; ? ? ?
sFilterConfig.FilterMaskIdHigh?=ANOTHER_SENSOR_BOARD_CAN_ID<<5;??
sFilterConfig.FilterMaskIdLow??=THIRD_SENSOR_BOARD_CAN_ID?<<5;???
sFilterConfig.FilterFIFOAssignment?=?CAN1FIFO;????//接收到的報文放入到FIFO0中 ??
sFilterConfig.FilterActivation?=?ENABLE;????//激活過濾器??
sFilterConfig.SlaveStartFilterBank??=?0; ??
HAL_Status=HAL_CAN_ConfigFilter(hcan,?&sFilterConfig);??
?HAL_Status=HAL_CAN_Start(&hcan1);??//開啟CAN??
?if(HAL_Status!=HAL_OK){??
????printf("開啟CAN失敗\r\n");????
?}????
?HAL_Status=HAL_CAN_ActivateNotification(&hcan1,???CAN_IT_RX_FIFO0_MSG_PENDING);??
?if(HAL_Status!=HAL_OK){??
????printf("開啟掛起中段允許失敗\r\n");?????
??}??
}??
void?HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef?*hcan)??//接收回調(diào)函數(shù)??
{??
uint8_t??Data[8];??
HAL_StatusTypeDef???HAL_RetVal;??
if(hcan?==&hcan1){????
??HAL_RetVal=HAL_CAN_GetRxMessage(&hcan1,??CAN1FIFO,?&RxMeg,??Data);??
??if?(?HAL_OK==HAL_RetVal)??
??{???????????????????????????????????????????
??????//在這里接收數(shù)據(jù)??
???}??
}??
//發(fā)送數(shù)據(jù)函數(shù)??
uint8_t?CANx_SendNormalData(CAN_HandleTypeDef*?hcan,uint16_t?ID,uint8_t?*pData,uint16_t?Len)??
{??
????HAL_StatusTypeDef???HAL_RetVal;??
????????uint16_t?SendTimes,SendCNT=0;??
????uint8_t??FreeTxNum=0;??
????TxMeg.StdId=ID;??
????if(!hcan?||?!?pData?||!Len)??return?1;??
????SendTimes=Len/8+(Len%8?1:0);??
????FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);??
????TxMeg.DLC=8;??
????while(SendTimes--){??
????????if(0==SendTimes){??
????????????if(Len%8)??
????????????????TxMeg.DLC=Len%8;??
????????}??
????????while(0==FreeTxNum){??
????????????FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);??
????????}??
????????HAL_Delay(1);???//沒有延時很有可能會發(fā)送失敗??
????????HAL_RetVal=HAL_CAN_AddTxMessage(&hcan1,&TxMeg,pData+SendCNT,(uint32_t*)CAN_TX_MAILBOX0);???
????????if(HAL_RetVal!=HAL_OK)??
????????{??
????????????return?2;??
????????}??
????????SendCNT+=8;??
????}??
??return?0;??
}</code>??
2、在main.c中的? /* USER CODE BEGIN 2 */ ?和?/* USER CODE END 2 */ 之間調(diào)用用戶初始化CAN函數(shù):CAN_User_Init( &hcan1 ) 朽寞。
在主循環(huán)中定時調(diào)用發(fā)送數(shù)據(jù)函數(shù)uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)發(fā)送數(shù)據(jù)即可识窿。
需要注意的是CAN的收發(fā)必須要有發(fā)送者和接收者,否則失敗脑融。
---------------------------------------------------------------------------------