为了使用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.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK);
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);