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'; 

  这样基本思路就改的差不多了。其余的一些按照报错来改就可以了。

 

posted on 2017-04-24 20:42  Rogueman  阅读(1085)  评论(0)    收藏  举报

导航