1. 程式人生 > >STM32 HAL庫學習(三)ADC取樣以及printf的使用

STM32 HAL庫學習(三)ADC取樣以及printf的使用

ADC輸出的電壓值經轉換後一般為一個浮點數,要將其列印到串列埠則需要對串列埠輸出函式做一個調整。

首先是printf函式的重定向,將一下程式碼加入到usart.c中,完成後便可以用printf函式輸出字串到串列埠中,而要輸出浮點數,則還需在“專案/建立設定/C Linker/Miscellaneous/Other options”中新增“-u _printf_float”

#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);
	return ch;
}
#endif
int _write(int file,char*ptr,int len)
{
	int Dataldx;
	for(Dataldx = 0;Dataldx < len;Dataldx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}

接下來是配置ADC取樣,ADC取樣可以配置為單通道、多通道,連續、非連續等取樣模式,傳輸獲取取樣值的方式也有查詢獲取、中斷獲取以及DMA獲取等方式,都有提供相應的HAL庫函式。

STM32F070的ADC時鐘來源主要有兩種方式:

  • 直接來源於HSI 14MHZ,也是可配置的最大時鐘頻率,對應在CubeMX中的Clock Prescaler配置為Asynchronous clock mode
  • 來源於APB時鐘的2分頻或者4分頻(但最大都不能超過14MHZ)

獲取ADC取樣值的方式

1、查詢方式獲取ADC取樣值

  查詢方式主要用到的函式是HAL_ADC_Start()、HAL_ADC_PollForConversion()以及HAL_ADC_GetValue(),其中,HAL_ADC_Start是軟體開始ADC轉換,PollForConversion則等待ADC轉換完成,當轉換完成後,既可在主函式中呼叫HAL_ADC_GetValue獲取取樣值,進行相應的轉換和輸出。

uint32_t value = 0;
float vol = 0;
while(1)
{
   /*USER CODE BEGIN WHILE*/
   HAL_ADC_Start(&hadc);
   HAL_ADC_PollForConversion(&hadc,HAL_DELAY_MAX);
   value = HAL_ADC_GetValue(&hadc);
   vol = (float)(value *3.3/4096);
   printf("%.2f",vol);
   HAL_Delay(1000);
   /*USER CODE END WHILE*/
}

2、DMA中斷方式 

當ADC取樣方式配置為連續取樣時,可以藉助DMA對取樣值進行儲存,當DMA傳輸完成時產生中斷,再在中斷函式中對取樣到的資料進行處理。具體步驟是:在CubeMX中配置DMA Request為ADC,對應的選擇通道DMA1 Channel1,資料寬度選擇word(因為ADC取樣值型別為uint32_t),generate code。在main函式中呼叫HAL_ADC_Start_DMA(),配置DMA資料儲存的位置以及傳輸的資料個數。假設設定資料個數為100,則當ADC取樣並轉換100個數據後,DMA這邊接收到100個數據後則會產生DMA中斷。而當DMA中斷產生時,HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)先是判斷是傳輸一半資料中斷標誌還是傳輸完成中斷標誌,再根據繫結的控制代碼呼叫相應的回撥函式。而當選擇ADC DMA傳輸時,DMA傳輸完成後其回撥函式會呼叫 HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc),因此只需重寫該函式進行資料處理即可。(對於這一點,檢視DMA_IRQHandler可以發現其根據控制代碼呼叫相應的回撥函式。但是目前我還沒找到在哪裡呼叫了HAL_ADC_ConvCpltCallback........存疑)

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
   uint32_t value = 0;
   float vol = 0;
   value = ADC_Data[0];
   vol = (float)(3.3*value);
   vol = (float)vol/4096;
   printf("%.3f",vol);
   printf("\r\n");
}