STM32CubeMX与HAL库学习--简单的CAN回环测试
STM32CubeMX與HAL庫學習--簡單的CAN回環測試
- 前言
- STM32CubeMX生成初始化代碼
- 在MDK-ARM里編輯代碼
- 其他
- 后續
前言
本人小白,最近看了CAN協議與STM32的bxCAN外設的一些資料,簡單地做個CAN回環測試練習一下。這只是一個初學者的簡單練習記錄,學習的話還是要看對應的教程啦。
使用到的工具及版本:
STM32CubeMX版本:6.3.0
HAL庫:STM32CubeF4 Firmware Package V1.26.1
MDK-ARM:V5.32.0.0
開發板:野火的霸天虎開發板V2(主控芯片是STM32F407ZGT6)
大概的框圖如下:
STM32CubeMX生成初始化代碼
時鐘、串口配置之類的略過。
關于CAN配置:
在NVIC那里打開CAN1 RX0中斷允許,并設定一下優先級。
在MDK-ARM里編輯代碼
CAN的設置尚未完成,CubeMX那里只是設置了模式,打開can.c,接下來設置篩選器。我配置的是列表模式,篩選了拓展ID 0x2233和標準ID 0。
/** 函數名:CAN_Filter_Config* 描述 :CAN的過濾器 配置* 輸入 :無* 輸出 : 無* 調用 :內部調用*/ static void CAN_Filter_Config(void) {CAN_FilterTypeDef CAN_FilterTypeDef;/*CAN篩選器初始化*/CAN_FilterTypeDef.FilterBank=0; //篩選器組0CAN_FilterTypeDef.FilterMode=CAN_FILTERMODE_IDLIST; //工作在列表模式CAN_FilterTypeDef.FilterScale=CAN_FILTERSCALE_32BIT; //篩選器位寬為單個32位。/* 使能篩選器,按照標志的內容進行比對篩選,擴展ID不是如下的就拋棄掉,是的話,會存入FIFO0。 */CAN_FilterTypeDef.FilterIdHigh= ((((uint32_t)0x2233<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16; //要篩選的ID高位 CAN_FilterTypeDef.FilterIdLow= (((uint32_t)0x2233<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要篩選的ID低位 CAN_FilterTypeDef.FilterMaskIdHigh= 0; //第二個ID的高位CAN_FilterTypeDef.FilterMaskIdLow= 0; //第二個ID的低位CAN_FilterTypeDef.FilterFIFOAssignment=CAN_FILTER_FIFO0 ; //篩選器被關聯到FIFO0CAN_FilterTypeDef.FilterActivation=ENABLE; //使能篩選器HAL_CAN_ConfigFilter(&hcan1,&CAN_FilterTypeDef); }發送或者接收數據都有對應的結構體對幀的ID、幀類別、數據長度等進行了描述(CAN_RxHeaderTypeDef、CAN_TxHeaderTypeDef),發送時需要根據數據特性配置發送結構體,接收則是把接收數據的特性存儲到指定的接收結構體。
消息發送函數
獲取接收消息函數
因為只是簡單的測試,我就在初始化階段把他們設置好。
用一個CAN_Config把CAN的功能完整。
在CubeMX生成的CAN1初始化函數中調用自己寫的CAN_Config(),完成CAN的設置并開啟它。
FIFO0接收到數據的中斷回調函數與CAN錯誤回調函數如下。
main函數。
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ extern __IO uint32_t CAN_RxFlag; //用于標志是否接收到數據,在中斷函數中賦值extern uint8_t CAN_TxDate[9]; //發送緩沖區 extern uint8_t CAN_RxDate[9]; //接收緩沖區extern CAN_TxHeaderTypeDef TxMes; //發送結構體 extern CAN_RxHeaderTypeDef RxMes; //接收結構體 extern uint32_t TxMailbox; //用于指示CAN消息發送函數HAL_CAN_AddTxMessage使用了哪個郵箱來發送數據 /* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/ int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_CAN1_Init();/* Initialize interrupts */MX_NVIC_Init();/* USER CODE BEGIN 2 */printf("CAN LOOP TEST\r\n");HAL_CAN_AddTxMessage(&hcan1, &TxMes, CAN_TxDate, &TxMailbox); //發送數據/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */if(CAN_RxFlag){CAN_RxFlag = 0;printf("Transmit message:%s\r\n",CAN_TxDate);printf("Receive message:%s\r\n",CAN_RxDate);}/* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }效果
其他
最初,我把發送數組和接收數組的長度設為8
uint8_t CAN_TxDate[8]="CAN LOOP"; //發送緩沖區 uint8_t CAN_RxDate[8]; //接收緩沖區結果是這樣:
不出意外的話這兩個數組在內存中是這樣的(注:其實可以在map文件里查看具體地址):
如果只是用來存儲CAN數據這倒是沒什么問題,但是用printf把它們作為字符數組輸出的話就可能會像圖中一樣越界了。
所以我把這兩個數組長度定義為9,0~7字節是數據,第8字節一直是0(編譯器給它初始化為0),這樣就可以防止printf輸出越界。
后續
接下來,在原來的基礎上增加一個按鍵,把按鍵按下次數轉換為字符串存儲到CAN_TxDate數組,并在按鍵按下的中斷里通過CAN發送,其他基本與上文無異,我的實現步驟如下:
首先打開原來的CubeMX工程文件,找到按鍵的引腳,把它配置為外部中斷
使能中斷
然后就可以生成代碼了,別忘了勾選保留用戶代碼
寫在用戶區域的代碼會得以保留,寫的時候注意一下位置,我前面while循環里的代碼寫錯位置了,重新生成文件時就被刪了。
正確的位置
錯誤的位置
/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */if(CAN_RxFlag){CAN_RxFlag = 0;printf("Transmit message:%s\r\n",CAN_TxDate);printf("Receive message:%s\r\n",CAN_RxDate);}/* USER CODE BEGIN 3 */}/* USER CODE END 3 */其實看注釋名字就知道了。
在main.c里增加了按鍵中斷的回調函數。
刪除了main函數里的CAN數據發送HAL_CAN_AddTxMessage(&hcan1, &TxMes, CAN_TxDate, &TxMailbox);
這樣,數據只在按鍵按下時發送,其他不變。
結果
總結
以上是生活随笔為你收集整理的STM32CubeMX与HAL库学习--简单的CAN回环测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hypermesh 圆周阵列-插件
- 下一篇: 如何将PPT转换成Word文档?