×
单片机 > 单片机程序设计 > 详情

STM32-HAL

发布时间:2020-08-25 发布时间:
|

    为了使用STM32 cubeMX工具快速完成设计,打算从StdPeriph_Lib换成HAL_Driver。初使用cubeMX,感觉就像从DOS时代迈入图形界面时代,而且对STM的所有系列有最好的支持。


在HAL库中:


常用功能:


HAL_Delay()  //毫秒延时,精度还是可以的。

HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);//GPIO_PIN_RESET而不是RESET了。




时钟配置:


     如果懂得STM32的架构,配置起来简直不能太简单,但好像有个bug就是配置为HSI时钟无法DEBUG调试。




串口中断:


通过HAL_UART_GetState(&huart1)获得当前的状态,返回的类型有:


typedef enum

{

  HAL_UART_STATE_RESET             = 0x00,    /*!< Peripheral is not initialized                      */

  HAL_UART_STATE_READY             = 0x01,    /*!< Peripheral Initialized and ready for use           */

  HAL_UART_STATE_BUSY              = 0x02,    /*!< an internal process is ongoing                     */

  HAL_UART_STATE_BUSY_TX           = 0x12,    /*!< Data Transmission process is ongoing               */

  HAL_UART_STATE_BUSY_RX           = 0x22,    /*!< Data Reception process is ongoing                  */

  HAL_UART_STATE_BUSY_TX_RX        = 0x32,    /*!< Data Transmission and Reception process is ongoing */

  HAL_UART_STATE_TIMEOUT           = 0x03,    /*!< Timeout state                                      */

  HAL_UART_STATE_ERROR             = 0x04     /*!< Error                                              */

}HAL_UART_StateTypeDef;


在中断处理函数HAL_UART_IRQHandler(UART_HandleTypeDef *huart)中,逐个获取各种状态:


    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE); 


    ......


    如果没有错误就再进入对应的收发处理函数:


    if((tmp_flag != RESET) && (tmp_it_source != RESET))   UART_Receive_IT(huart);


    在UART_Receive_IT(UART_HandleTypeDef *huart)函数中通过调用回调函数HAL_UART_RxCpltCallback(huart)进行相关接收数据的处理, HAL_UART_RxCpltCallback(huart)一般会被我们在APP中复习定义,其中非常重要的是需要在其末尾通过再次调用HAL_UART_Receive_IT(&huart1,(uint8_t *)RxBuffer,1)完成连续的中断接收。


 


串口状态的错误类型如下:

#define HAL_UART_ERROR_NONE      ((uint32_t)0x00)    /*!< No error            */

#define HAL_UART_ERROR_PE        ((uint32_t)0x01)    /*!< Parity error        */

#define HAL_UART_ERROR_NE        ((uint32_t)0x02)    /*!< Noise error         */

#define HAL_UART_ERROR_FE        ((uint32_t)0x04)    /*!< frame error         */

#define HAL_UART_ERROR_ORE       ((uint32_t)0x08)    /*!< Overrun error       */

#define HAL_UART_ERROR_DMA       ((uint32_t)0x10)    /*!< DMA transfer error  */


ST库中,USART Flags的定义:


#define USART_FLAG_CTS                       ((uint16_t)0x0200)

#define USART_FLAG_LBD                       ((uint16_t)0x0100)

#define USART_FLAG_TXE                       ((uint16_t)0x0080)

#define USART_FLAG_TC                        ((uint16_t)0x0040)

#define USART_FLAG_RXNE                      ((uint16_t)0x0020)

#define USART_FLAG_IDLE                      ((uint16_t)0x0010)

#define USART_FLAG_ORE                       ((uint16_t)0x0008)

#define USART_FLAG_NE                        ((uint16_t)0x0004)

#define USART_FLAG_FE                        ((uint16_t)0x0002)

#define USART_FLAG_PE                        ((uint16_t)0x0001)


     STM32存在的一个广为人知的硬件BUG就是一直进入ORE状态,在ST标准库中可以通过USART_ClearFlag或者ClearITPendingBit清掉错误标记来解决。


可以使用暴力解决办法,完全复写串口中断处理函数(将原来的注释掉):


void USART1_IRQHandler(void)

{

    unsigned char code; 

    printf("TEST for RX \n");

    if(USART1->SR&(1<<5))

    {     

       code=USART1->DR;     //串口数据寄存器读取数据后会自动清理掉接收中断标记,不需要再单独处理

       printf("GET from RX:%c \n",code);

    }

}


    感觉对于STM32的诸多bug,都可以通过直接操作寄存器来解决,而且操作寄存器最麻烦的是在外设的初始化阶段,后期需要管理的不过是些SR、DR之类的了。


   tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);

  /* UART Over-Run interrupt occurred ----------------------------------------*/

  if((tmp_flag != RESET) && (tmp_it_source != RESET))

  { 

      huart->ErrorCode |= HAL_UART_ERROR_ORE;

      printf("usart1 error Over-Run \n");

      //__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE);  //也可以在此添加清标记的代码


  }


本文最后总结:


在HAL库的main文件中,第一次调用中断以使能中断时,接收的数量即size最好设1,如果不为1你在测试中断的时候又发一个字节,很难一下子发现问题。


    if(HAL_UART_Receive_IT(&huart1,(uint8_t *)rxBuffer, size) != HAL_OK)  Error_Handler();




ADC执行:


MX_ADC1_Init();


HAL_ADCEx_Calibration_Start(&hadc1); 


HAL_ADC_Start_DMA(&hadc1, ADC_Data,5); //DMA获取


或者是轮询获取方式:


//HAL_ADC_Start(&hadc1);

//while(__HAL_ADC_GET_FLAG(&hadc1,ADC_FLAG_EOC)==RESET);


//uint16_t adc= HAL_ADC_GetValue(&hadc1);


使用CUBE配置的DMA ADC多路采样:


adc 0 value: 103089701


adc 1 value: 103155237


adc 2 value: 1574


adc 3 value: 0


adc 4 value: 0


adc 5 value: 0 


采集的数据不对,根据网上获知的他人类似经验:可能是底层函数没有将CHANNEL清零导致。如下方式可以完成多通道的采集:


  while (1)

  {



     sConfig.Channel = ADC_CHANNEL_VREFINT;

    sConfig.Rank = 1;

     sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK);

    HAL_ADC_Start(&hadc1);

     HAL_ADC_PollForConversion(&hadc1,10);

    uint16_t adc= HAL_ADC_GetValue(&hadc1);

    printf("\n VREFINT value: %-4d",adc);

    HAL_ADC_Stop(&hadc1);

   

     sConfig.Channel = ADC_CHANNEL_1;

    sConfig.Rank = 1;                     //这个一定都是设置为1,不然每次获得的数据都是Rank = 1通道的数据

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK);

    HAL_Delay(100);

    HAL_ADC_Start(&hadc1);

    HAL_ADC_PollForConversion(&hadc1,10);

    adc= HAL_ADC_GetValue(&hadc1);

    printf("\n adc1 value: %-4d",adc);

    HAL_ADC_Stop(&hadc1);

}

关键字:STM32  HAL 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于ARM控制器和GPRS技术网络实现配变监控系统的设计