STM32CubeMX与HAL库学习--简单的CAN回环测试
STM32CubeMX與HAL庫(kù)學(xué)習(xí)--簡(jiǎn)單的CAN回環(huán)測(cè)試
- 前言
- STM32CubeMX生成初始化代碼
- 在MDK-ARM里編輯代碼
- 其他
- 后續(xù)
前言
本人小白,最近看了CAN協(xié)議與STM32的bxCAN外設(shè)的一些資料,簡(jiǎn)單地做個(gè)CAN回環(huán)測(cè)試練習(xí)一下。這只是一個(gè)初學(xué)者的簡(jiǎn)單練習(xí)記錄,學(xué)習(xí)的話還是要看對(duì)應(yīng)的教程啦。
使用到的工具及版本:
STM32CubeMX版本:6.3.0
HAL庫(kù):STM32CubeF4 Firmware Package V1.26.1
MDK-ARM:V5.32.0.0
開(kāi)發(fā)板:野火的霸天虎開(kāi)發(fā)板V2(主控芯片是STM32F407ZGT6)
大概的框圖如下:
STM32CubeMX生成初始化代碼
時(shí)鐘、串口配置之類(lèi)的略過(guò)。
關(guān)于CAN配置:
在NVIC那里打開(kāi)CAN1 RX0中斷允許,并設(shè)定一下優(yōu)先級(jí)。
在MDK-ARM里編輯代碼
CAN的設(shè)置尚未完成,CubeMX那里只是設(shè)置了模式,打開(kāi)can.c,接下來(lái)設(shè)置篩選器。我配置的是列表模式,篩選了拓展ID 0x2233和標(biāo)準(zhǔn)ID 0。
/** 函數(shù)名:CAN_Filter_Config* 描述 :CAN的過(guò)濾器 配置* 輸入 :無(wú)* 輸出 : 無(wú)* 調(diào)用 :內(nèi)部調(diào)用*/ 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; //篩選器位寬為單個(gè)32位。/* 使能篩選器,按照標(biāo)志的內(nèi)容進(jìn)行比對(duì)篩選,擴(kuò)展ID不是如下的就拋棄掉,是的話,會(huì)存入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; //第二個(gè)ID的高位CAN_FilterTypeDef.FilterMaskIdLow= 0; //第二個(gè)ID的低位CAN_FilterTypeDef.FilterFIFOAssignment=CAN_FILTER_FIFO0 ; //篩選器被關(guān)聯(lián)到FIFO0CAN_FilterTypeDef.FilterActivation=ENABLE; //使能篩選器HAL_CAN_ConfigFilter(&hcan1,&CAN_FilterTypeDef); }發(fā)送或者接收數(shù)據(jù)都有對(duì)應(yīng)的結(jié)構(gòu)體對(duì)幀的ID、幀類(lèi)別、數(shù)據(jù)長(zhǎng)度等進(jìn)行了描述(CAN_RxHeaderTypeDef、CAN_TxHeaderTypeDef),發(fā)送時(shí)需要根據(jù)數(shù)據(jù)特性配置發(fā)送結(jié)構(gòu)體,接收則是把接收數(shù)據(jù)的特性存儲(chǔ)到指定的接收結(jié)構(gòu)體。
消息發(fā)送函數(shù)
獲取接收消息函數(shù)
因?yàn)橹皇呛?jiǎn)單的測(cè)試,我就在初始化階段把他們?cè)O(shè)置好。
用一個(gè)CAN_Config把CAN的功能完整。
在CubeMX生成的CAN1初始化函數(shù)中調(diào)用自己寫(xiě)的CAN_Config(),完成CAN的設(shè)置并開(kāi)啟它。
FIFO0接收到數(shù)據(jù)的中斷回調(diào)函數(shù)與CAN錯(cuò)誤回調(diào)函數(shù)如下。
main函數(shù)。
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ extern __IO uint32_t CAN_RxFlag; //用于標(biāo)志是否接收到數(shù)據(jù),在中斷函數(shù)中賦值extern uint8_t CAN_TxDate[9]; //發(fā)送緩沖區(qū) extern uint8_t CAN_RxDate[9]; //接收緩沖區(qū)extern CAN_TxHeaderTypeDef TxMes; //發(fā)送結(jié)構(gòu)體 extern CAN_RxHeaderTypeDef RxMes; //接收結(jié)構(gòu)體 extern uint32_t TxMailbox; //用于指示CAN消息發(fā)送函數(shù)HAL_CAN_AddTxMessage使用了哪個(gè)郵箱來(lái)發(fā)送數(shù)據(jù) /* 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); //發(fā)送數(shù)據(jù)/* 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 */ }效果
其他
最初,我把發(fā)送數(shù)組和接收數(shù)組的長(zhǎng)度設(shè)為8
uint8_t CAN_TxDate[8]="CAN LOOP"; //發(fā)送緩沖區(qū) uint8_t CAN_RxDate[8]; //接收緩沖區(qū)結(jié)果是這樣:
不出意外的話這兩個(gè)數(shù)組在內(nèi)存中是這樣的(注:其實(shí)可以在map文件里查看具體地址):
如果只是用來(lái)存儲(chǔ)CAN數(shù)據(jù)這倒是沒(méi)什么問(wèn)題,但是用printf把它們作為字符數(shù)組輸出的話就可能會(huì)像圖中一樣越界了。
所以我把這兩個(gè)數(shù)組長(zhǎng)度定義為9,0~7字節(jié)是數(shù)據(jù),第8字節(jié)一直是0(編譯器給它初始化為0),這樣就可以防止printf輸出越界。
后續(xù)
接下來(lái),在原來(lái)的基礎(chǔ)上增加一個(gè)按鍵,把按鍵按下次數(shù)轉(zhuǎn)換為字符串存儲(chǔ)到CAN_TxDate數(shù)組,并在按鍵按下的中斷里通過(guò)CAN發(fā)送,其他基本與上文無(wú)異,我的實(shí)現(xiàn)步驟如下:
首先打開(kāi)原來(lái)的CubeMX工程文件,找到按鍵的引腳,把它配置為外部中斷
使能中斷
然后就可以生成代碼了,別忘了勾選保留用戶代碼
寫(xiě)在用戶區(qū)域的代碼會(huì)得以保留,寫(xiě)的時(shí)候注意一下位置,我前面while循環(huán)里的代碼寫(xiě)錯(cuò)位置了,重新生成文件時(shí)就被刪了。
正確的位置
錯(cuò)誤的位置
/* 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 */其實(shí)看注釋名字就知道了。
在main.c里增加了按鍵中斷的回調(diào)函數(shù)。
刪除了main函數(shù)里的CAN數(shù)據(jù)發(fā)送HAL_CAN_AddTxMessage(&hcan1, &TxMes, CAN_TxDate, &TxMailbox);
這樣,數(shù)據(jù)只在按鍵按下時(shí)發(fā)送,其他不變。
結(jié)果
總結(jié)
以上是生活随笔為你收集整理的STM32CubeMX与HAL库学习--简单的CAN回环测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hypermesh 圆周阵列-插件
- 下一篇: 首次打开vue运行出错,error Ex