STM32F0在hal库中移植usmart
最早接触usmart是在原子的开发板上,那时候用usamrt调了不少程序。后来实验室项目用到了stm32f072,于是就把usmart移植到了f0上面。好在这方面已经有人做过了,直接把代码拿来用就行。
最近板子更新,芯片换了个容量,但还是072。可不知道怎么回事,用标准库的程序死活运行不了。于是死马当活马医,用cube生成了初始化代码,竟然可以了。表示真是十分玄学。于是哼哧哼哧,把外围的驱动也都移植到了hal库上面。总体来说,hal库没有标准库直观。相信用惯了标准库用hal库开始都会很迷。各种结构体,函数等等跳来跳去。但是hal库也有好用便利的地方,至少初始化这块可以直接用cube来生成了。一些外设的使用也比较直观。缺点是管得太多,尤其是中断处理这块。
下面就来说说移植usamrt的思路。其实主要的部分就两块。定时器和串口。定时器的话,就用TIM14就行,配置成向上计数。这一块cube可以直接生成,具体看代码:
1 static void MX_TIM14_Init(void) 2 { 3 4 htim14.Instance = TIM14; 5 htim14.Init.Prescaler = 4799; 6 htim14.Init.CounterMode = TIM_COUNTERMODE_UP; 7 htim14.Init.Period = 1000;//100ms 中断一次 8 htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 9 if (HAL_TIM_Base_Init(&htim14) != HAL_OK) 10 { 11 Error_Handler(); 12 } 13 14 }
另外全局中断在cube里面是要开的,这样在这段代码中调用的HAL_TIM_Base_MspInit()中才会添加
HAL_NVIC_SetPriority(TIM14_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM14_IRQn);
这两句代码。当然你不使能,自己加也是可以的,不要忘记就行。最后不要忘记main函数里加一句 HAL_TIM_Base_Start_IT(&htim14);我开始的时候就是没加,调试的时候发现看控制寄存器发现没使能,然后去翻hal的头文件才发现还有这一句函数。
串口的初始化也一样很简单,在cube里直接就配置生成就行了。这方面确实hal库很方便。相关配置:
1 static void MX_USART1_UART_Init(void) 2 { 3 4 huart1.Instance = USART1; 5 huart1.Init.BaudRate = 9600; 6 huart1.Init.WordLength = UART_WORDLENGTH_8B; 7 huart1.Init.StopBits = UART_STOPBITS_1; 8 huart1.Init.Parity = UART_PARITY_NONE; 9 huart1.Init.Mode = UART_MODE_TX_RX; 10 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; 11 huart1.Init.OverSampling = UART_OVERSAMPLING_16; 12 huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; 13 huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; 14 if (HAL_UART_Init(&huart1) != HAL_OK) 15 { 16 Error_Handler(); 17 } 18 19 }
同样中断使能不要忘记,之后在usmart相关文件里面,把初始化的部分删删掉就可以了。
重点就是,中断怎么写。
首先我们看串口的中断实现。在hal库中中断接受使用这个函数HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)。可以看出来,它一下就把接受长度定死了。虽然单个字符接受依旧进入USART1_IRQHandler这个函数,但是数据不装满buff,中断是不会调用HAL_UART_RxCpltCallback这个回调处理函数的。然而我们的函数长度是不定的。所以必须要想个办法解决。
所以我的想法是,使用定时器中断,中断每100ms中断一次,每中断一次,我就检查一次buff,看看数据接受完没有。但是我们不可能一个个去查的。所以只要我们是发送"\r\n"结尾,我们只要检查最后一个字符是不是’\n‘就行了。具体代码实现如下:
1 //中断服务 2 /* 3 typedef struct 4 { 5 uint16_t RC :1; 6 uint16_t RD :1; 7 uint16_t count :14;//16383 bytes 8 9 }usart_bitfield; 10 usart_bitfield USART_STA; 11 */ 12 void USART1_IRQHandler(void) 13 { 14 HAL_UART_IRQHandler(&huart1); 15 USART_STA.count++; //记录接收长度 16 } 17 18 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 19 { 20 21 printf("usart buff overflow/r/n");//事实上我们不可能用完缓冲,所以实际上是溢出了 22 USART_STA.count=0; 23 USART_STA.RC=0; 24 USART_STA.RD=0; 25 HAL_UART_Receive_IT(&huart1, usart_rx_buff, 64);//重启中断接收 26 27 } 28 void TIM14_IRQHandler(void) 29 { 30 /* USER CODE BEGIN TIM14_IRQn 0 */ 31 32 /* USER CODE END TIM14_IRQn 0 */ 33 HAL_TIM_IRQHandler(&htim14); 34 /* USER CODE BEGIN TIM14_IRQn 1 */ 35 36 37 } 38 39 /* USER CODE END TIM14_IRQn 1 */ 40 41 //callback 42 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 43 { 44 char *p; 45 localtime++; //做个本地时间戳,充分利用一下 46 47 if(usart_rx_buff[USART_STA.count-1]==0x0a)//'/n'received 48 { 49 if(usart_rx_buff[USART_STA.count-2]==0x0d)//'/r'received 50 { 51 USART_STA.RC=1; 52 __HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE); 53 54 /* Disable the UART Parity Error Interrupt */ 55 __HAL_UART_DISABLE_IT(&huart1, UART_IT_PE); 56 57 /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ 58 __HAL_UART_DISABLE_IT(&huart1, UART_IT_ERR); 59 60 /* Rx process is completed, restore huart->RxState to Ready */ 61 huart1.RxState = HAL_UART_STATE_READY; 62 63 usmart_dev.scan(); 64 TIM14->ARR=1000; 65 TIM14->CNT=0; 66 USART_STA.count=0; 67 USART_STA.RC=0; 68 USART_STA.RD=0; 69 } 70 else 71 { 72 printf("usart receive error/r/n"); 73 USART_STA.count=0; 74 USART_STA.RC=0; 75 USART_STA.RD=0; 76 __HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE); 77 78 /* Disable the UART Parity Error Interrupt */ 79 __HAL_UART_DISABLE_IT(&huart1, UART_IT_PE); 80 81 /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ 82 __HAL_UART_DISABLE_IT(&huart1, UART_IT_ERR); 83 84 /* Rx process is completed, restore huart->RxState to Ready */ 85 huart1.RxState = HAL_UART_STATE_READY; 86 //restart receive 87 HAL_UART_Receive_IT(&huart1, usart_rx_buff, 64); 88 89 } 90 //stub; 91 } 92 TIM14->SR&=~1;//clear update flag 93 }
最后注意一下,usmart_scan()中要改一下
if(USART_STA.RC)
len=USART_STA.count;
USART_RX_BUF[len-2]='\0';
这样基本思路就改的差不多了。其余的一些按照报错来改就可以了。
浙公网安备 33010602011771号