[STM32CubeMX]學習筆記5:ADC模數轉換電壓至串口輸出

 

MCU:STM32F103ZET6

IDE:  MDK-ARM V5 +STM32CubeMX5.0.0

串口調試助手:SSCOM3.2

 

功能描述:通過ADC1通道1採樣外部電壓值,將採樣的AD值和轉換後的電壓值通過串口打印出來。需要配置的有USART1和ADC。

一. 在 Pinout&Configuration---System Core中:

  • 1. 首先設置時鐘RCC的HSE(外部高速時鐘)爲晶振模式:Crystal/ceramic Resonator

  • 2. 設置系統SYS的Debug爲Serial Wire:

二. 在 Pinout&Configuration---Analog和Connectivity中:

  • 1. 設置PA1爲ADC1_IN1模式:

根據原理圖可知ADC1的通道1的引腳爲PA1,因此設置PA1爲ADC1_IN1模式。

        

  • 2. 在Configuration的Parameter Settings中設置ADC1的參數:

分別設置模式,單單個掃描和單次掃描,並在規則通道參數設置中設置爲軟件觸發的方式。(對應的標準庫代碼在右上角)。

  • 3. 打開USART1,並設置模式爲異步收發模式Asynchronous:

  • 4. 設置USART1的參數,通用的“96-N-8-1”模式,即波特率9600,N校驗位(無校驗),數據位數爲8,停止位爲1位:

三.在 Clock Configuration中:

配置時鐘爲72 Mhz。

四.在 Project Manager---Project中:

  • 1.設置項目的名稱以及保存的位置,選擇Toolchain/IDE爲MDK-ARM V5,

Tips:最好把Linker Settings中的Minimum Heap Size設置爲0x600。

  • 2.在Code Generator選項中如下勾選:

最後點Generate Code生成代碼,並選擇“Open Project”:

五.代碼分析與改寫:

和筆記4相同,同樣需要用到串口輸出的功能,首先將printf()函數的輸出功能映射到串口上:

  • 1. 首先在main.c中進行宏定義:

/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	
#endif /* __GNUC__ */
  • 2. 對於MDK-ARM編譯器,在main.c中加入重定向函數:(此處與官方例程中不同,將&UartHandle改爲&huart1)
/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
	
	return ch;
}
/* USER CODE END 0 */

3. 在main.c中設置變量用於存儲AD和電壓值:(注意VOL_Value一定是浮點型的)

 /* USER CODE BEGIN 1 */
uint16_t ADC_Value;
float VOL_Value;
  /* USER CODE END 1 */

4.在while(1)循環中添加AD與電壓轉換程序:

步驟依次爲:

① HAL_ADCEx_Calibration_Start()//校準ADC

② HAL_ADC_Start()//開啓ADC

③ HAL_ADC_PollForConversion()//等待轉換過程

④若if循環判斷轉換完成後,HAL_ADC_GetState()獲取AD值存在ADC_Value中並打印。

⑤將AD值轉換爲電壓值存在VOL_Value中並打印。

/* USER CODE BEGIN WHILE */
  while (1)
  {
		HAL_ADCEx_Calibration_Start(&hadc1);  //校準
		HAL_ADC_Start(&hadc1);   //開啓
		HAL_ADC_PollForConversion(&hadc1,50);  //等待轉換完成
		
		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
		{
			ADC_Value=HAL_ADC_GetState(&hadc1);
			
			printf("檢測AD值爲:%d\r\n",ADC_Value);
			
			VOL_Value=ADC_Value*3.3/4096;
			
			printf("檢測電壓值爲:%.2fV \r\n",VOL_Value);
		}
		HAL_Delay(200);
		
		
    /* USER CODE END WHILE */

至此應該是完成了HAL庫下ADC轉換讀取電壓的程序,但是不知是硬件出了問題還是軟件有邏輯錯誤,我的電壓值一直很小,變化也不大,希望有遇到相同問題的朋友可以交流一下。(基於標準庫函數的程序也遇到了這個問題)。

2019/2/20 10:23 更新:

針對上述問題,經過反覆檢查程序找到了問題。源程序如下:

u16 Get_ADC_Value(u8 ch,u8 times)   //獲取AD轉換值的結果
{
	u8 t;
	u8 temp_val=0;
	ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); //最大的轉換週期,239.5個
	
	for (t=0;t<times;t++)
	{
		ADC_SoftwareStartConvCmd(ADC1,ENABLE); 
		while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));  //轉換完成後退出
		temp_val+=ADC_GetConversionValue(ADC1);
		delay_ms(5);
	}
	return temp_val/times;

temp_val的取值範圍是0-4095,因此應定義爲32位的變量:u8 temp_val=0→u32 temp_val=0;

針對HAL庫中程序,一定要定義VOL_Value爲浮點型的。

則會得到正確的結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章