ADC模擬采用功能)
一、功能通過PY32Studio可視化配置實(shí)現(xiàn)芯片內(nèi)部溫度傳感器Temperature、內(nèi)部參考電壓Vrefint、1/3的VCC的單次ADC采樣無需外接任何硬件電路最后通過串口printf實(shí)時(shí)打印芯片內(nèi)部結(jié)溫、內(nèi)部參考電壓、1/3的VCC。本練習(xí)采用單次轉(zhuǎn)換模式非掃描、非DMA配置簡單、代碼輕量化適合新手學(xué)習(xí)。二、硬件通過USB轉(zhuǎn)TTL模塊連接PC與Startkit板, Startkit板與USB轉(zhuǎn)TTL模塊的連線方式如下通過串口將信息發(fā)送到串口助手。Startkit 開發(fā)板USB轉(zhuǎn)TTL模塊Tx(PA0)RxRx(PA1)TxGNDGND三、PY32Studio配置3.1 創(chuàng)建一個新工程首先用PY32Studio創(chuàng)建一個F032_ADC1的新工程。3.2 配置時(shí)鐘在芯片視圖中點(diǎn)擊時(shí)鐘視圖在時(shí)鐘視圖中選擇HSI為時(shí)鐘源配置PLL_MULx9SYS_SELPLL系統(tǒng)時(shí)鐘為72MHz.3.3 配置UART1配置UART1的參數(shù)激活UART1配置UART1的參數(shù)波特率115200停止位1數(shù)據(jù)長度8位奇偶校驗(yàn)無。3.4 配置ADC的參數(shù)第一步配置ADC的內(nèi)部通道第二步配置ADC的參數(shù)Scan Conversion ModeDisable關(guān)閉掃描模式單次單通道采樣Continuous Conversion ModeDisable關(guān)閉連續(xù)轉(zhuǎn)換單次觸發(fā)單次采樣Discontinuous Conversion ModeDisable第三步配置ADC的轉(zhuǎn)換參數(shù)第四步配置ADC的轉(zhuǎn)換時(shí)間轉(zhuǎn)換時(shí)間長一點(diǎn)避免采樣波動第五步點(diǎn)擊生成工程四、理解HAL庫函數(shù)4.1 py32f032_hal_adc.cPY32 HAL 庫中與ADC相關(guān)的核心函數(shù)主要分為初始化配置、ADC轉(zhuǎn)換、中斷控制、回調(diào)函數(shù)等幾類。以下為核心函數(shù)詳解及使用示例一、 初始化與配置函數(shù)1.使能ADC外設(shè)前提必須在RCC層配置ADC時(shí)鐘。兩項(xiàng)時(shí)鐘配置是強(qiáng)制的ADC內(nèi)核時(shí)鐘也可作為轉(zhuǎn)換時(shí)鐘示例在 HAL_ADC_MspInit()推薦位置或者其他外設(shè)時(shí)鐘配置代碼中__HAL_RCC_ADC_CLK_ENABLE();(必須調(diào)用)ADC時(shí)鐘源與分頻系數(shù)在ADC初始化階段通過HAL_ADC_Init()的 ClockPrescaler 參數(shù)配置。2. ADC引腳配置使能ADC所用GPIO的時(shí)鐘使用宏__HAL_RCC_GPIOx_CLK_ENABLE()將ADC引腳配置為模擬模式使用函數(shù)HAL_GPIO_Init()3. 可選ADC使用中斷場景配置ADC的NVIC中斷使用HAL_NVIC_EnableIRQ(ADCx_IRQn)在對應(yīng)的中斷向量服務(wù)函數(shù)內(nèi)調(diào)用HAL_ADC_IRQHandler()4. 可選ADC使用DMA場景配置DMADMA通道、Normal/Circular模式等使用HAL_DMA_Init()配置DMA的NVIC中斷使用HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)在DMA中斷向量函數(shù)內(nèi)調(diào)用HAL_ADC_IRQHandler()二、ADC、規(guī)則組、通道參數(shù)配置1. 配置ADC基礎(chǔ)參數(shù)分辨率、數(shù)據(jù)對齊等和規(guī)則組參數(shù)轉(zhuǎn)換觸發(fā)源、序列器等HAL_ADC_Init()2. 配置規(guī)則組通道參數(shù)(通道號、在序列中的Rank序號等)HAL_ADC_ConfigChannel()3. 可選配置模擬看門狗監(jiān)控通道、高低閾值HAL_ADC_AnalogWDGConfig()三、ADC轉(zhuǎn)換1. 可選執(zhí)行ADC自動校準(zhǔn)提升轉(zhuǎn)換精度使用HAL_ADCEx_Calibration_Start()2. ADC驅(qū)動支持3種工作模式查詢輪詢、中斷、DMA傳輸輪詢模式Polling啟動ADC并開始轉(zhuǎn)換HAL_ADC_Start()等待轉(zhuǎn)換完成HAL_ADC_PollForConversion()讀取轉(zhuǎn)換結(jié)果HAL_ADC_GetValue()停止轉(zhuǎn)換關(guān)閉ADCHAL_ADC_Stop()中斷模式IT啟動ADC并開始轉(zhuǎn)換HAL_ADC_Start_IT()轉(zhuǎn)換完成觸發(fā)回調(diào)HAL_ADC_ConvCpltCallback()該函數(shù)需要用戶自行重寫讀取轉(zhuǎn)換結(jié)果HAL_ADC_GetValue()停止ADCHAL_ADC_Stop_IT()DMA模式啟動ADCDMAHAL_ADC_Start_DMA()轉(zhuǎn)換完成回調(diào)HAL_ADC_ConvCpltCallback()或DMA半傳輸回調(diào)HAL_ADC_ConvHalfBlockCpltCallback()回調(diào)由用戶實(shí)現(xiàn)DMA自動把采樣結(jié)果搬運(yùn)到目標(biāo)內(nèi)存CPU無需手動讀取DR寄存器停止ADCDMAHAL_ADC_Stop_DMA()四、回調(diào)函數(shù)如果啟用中斷用戶必須重寫的回調(diào)函數(shù)HAL_ADC_ErrorCallback()ADC錯誤回調(diào)HAL_ADC_LevelOutOfWindowCallback()模擬看門狗超限回調(diào)HAL_ADC_ConvCpltCallback()轉(zhuǎn)換完成回調(diào)HAL_ADC_ConvHalfBlockCpltCallbackDMA半滿回調(diào)五、編寫應(yīng)用代碼5.1 應(yīng)用代碼在PY32Studio生成的代碼的基礎(chǔ)上添加以下代碼首先定義幾個全局變量要把變量放在Private Variables下面的USER CODE段內(nèi);在uart.c文件中加入以下代碼包括“stdio.h”文件/* USER CODE BEGIN Includes */ #include stdio.h /* USER CODE END Includes */重寫fputc函數(shù)/* USER CODE BEGIN ExternalFunctions */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 1000); //阻塞式發(fā)送超時(shí)時(shí)間設(shè)為10001s return ch; } /* USER CODE END ExternalFunctions */在main()函數(shù)中在USER CODE BEGIN 1中加入ADC通道配置的結(jié)構(gòu)體變量。在while1循環(huán)中加入以下代碼配置ADC轉(zhuǎn)換通道配置ADC轉(zhuǎn)換通道的轉(zhuǎn)換序號配置ADC轉(zhuǎn)換時(shí)間ADC啟動ADC轉(zhuǎn)換等待ADC轉(zhuǎn)換完成讀取ADC轉(zhuǎn)換結(jié)果停止ADC轉(zhuǎn)換將轉(zhuǎn)換的結(jié)果轉(zhuǎn)化為溫度值VrefintVCCA/3打印轉(zhuǎn)換結(jié)果。int main(void) { /* USER CODE BEGIN 1 */ ADC_ChannelConfTypeDef sConfig {0}; //定義ADC通道配置的結(jié)構(gòu)體 /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ Studio_RCC_Init(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ Studio_GPIO_Init(); Studio_UART1_Init(); Studio_ADC1_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while(1) { sConfig.Channel ADC_CHANNEL_TEMPSENSOR; //配置ADC轉(zhuǎn)換的通道 sConfig.Rank ADC_REGULAR_RANK_1; //配置ADC轉(zhuǎn)換的序號 sConfig.SamplingTime ADC_SAMPLETIME_247CYCLES_5; //配置ADC轉(zhuǎn)換的時(shí)間 if (HAL_ADC_ConfigChannel(hadc1, sConfig) ! HAL_OK) //配置ADC的通道參數(shù) { Error_Handler(); } HAL_ADC_Start(hadc1); //啟動ADC轉(zhuǎn)換 HAL_ADC_PollForConversion(hadc1,10); //等待轉(zhuǎn)換完成 adcValue HAL_ADC_GetValue(hadc1); //讀取轉(zhuǎn)換結(jié)果 HAL_ADC_Stop(hadc1); //停止轉(zhuǎn)換 dTemperature __HAL_ADC_CALC_TEMPERATURE(TEMPSENSOR_CAL_VREFANALOG, adcValue, ADC_RESOLUTION_12B); //通過測量的電壓計(jì)算溫度 printf(Temperature is %d C.\r\n,(int)dTemperature); HAL_Delay(2000); sConfig.Channel ADC_CHANNEL_VREFINT; //配置ADC轉(zhuǎn)換的通道 sConfig.Rank ADC_REGULAR_RANK_1; //配置ADC轉(zhuǎn)換的序號 sConfig.SamplingTime ADC_SAMPLETIME_247CYCLES_5; //配置ADC轉(zhuǎn)換的時(shí)間 if (HAL_ADC_ConfigChannel(hadc1, sConfig) ! HAL_OK) //配置ADC的通道參數(shù) { Error_Handler(); } HAL_ADC_Start(hadc1); //啟動ADC轉(zhuǎn)換 HAL_ADC_PollForConversion(hadc1,10); //等待轉(zhuǎn)換完成 adcValue HAL_ADC_GetValue(hadc1); //讀取轉(zhuǎn)換結(jié)果 HAL_ADC_Stop(hadc1); //停止轉(zhuǎn)換 Vrefint adcValue * 0.0008; //計(jì)算Vrefint的電壓值 adcValue * VCCA/4096 printf(Vrefint is %.3f V \r\n,Vrefint); HAL_Delay(2000); sConfig.Channel ADC_CHANNEL_1_3VCCA; //配置ADC轉(zhuǎn)換的通道 sConfig.Rank ADC_REGULAR_RANK_1; //配置ADC轉(zhuǎn)換的序號 sConfig.SamplingTime ADC_SAMPLETIME_247CYCLES_5; //配置ADC轉(zhuǎn)換的時(shí)間 if (HAL_ADC_ConfigChannel(hadc1, sConfig) ! HAL_OK) //配置ADC的通道參數(shù) { Error_Handler(); } HAL_ADC_Start(hadc1); //啟動ADC轉(zhuǎn)換 HAL_ADC_PollForConversion(hadc1,10); //等待轉(zhuǎn)換完成 adcValue HAL_ADC_GetValue(hadc1); //讀取轉(zhuǎn)換結(jié)果 HAL_ADC_Stop(hadc1); //停止轉(zhuǎn)換 VCCA3 adcValue*0.0008; //計(jì)算VVCA/3的電壓值 adcValue * VCCA/4096 printf(VCCA/3 is %.3f V. \r\n,VCCA3); HAL_Delay(2000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }5.2 設(shè)置在選項(xiàng)卡中選擇安裝的編譯器版本和Debug類型。5.3 編譯下載點(diǎn)擊編譯圖標(biāo)開始編譯程序編譯成功后開始下載程序下載成功后開始調(diào)試程序5.4調(diào)試點(diǎn)擊調(diào)試圖標(biāo)進(jìn)入調(diào)試界面運(yùn)行程序把a(bǔ)dcValue、VCCA3、Vrefint、dTemperature四個變量加到Watch1窗口中。在View菜單中選擇Periodic Window Update命令全速運(yùn)行代碼觀察這幾個變量的值。打開串口助手選擇正確的端口名波特率數(shù)據(jù)位校驗(yàn)位和停止位打開串口開始接收數(shù)據(jù)。右面的窗口可以顯示出從MCU發(fā)送過來的數(shù)據(jù)。Vrefint和VCCA的值都是基于VCCA3.3V計(jì)算得出的。實(shí)際測量VCCA的電壓為3.36V。六、總結(jié)本章內(nèi)容我們采用單次采樣的查詢方式對ADC1內(nèi)部的3個通道進(jìn)行輪流采樣計(jì)算相應(yīng)的電壓值或溫度值并輪流打印計(jì)算結(jié)果。整個過程主要步驟如下通過PY32Studio配置時(shí)鐘UART1, ADC1模塊在uart.c文件中包括stdio.h頭文件重寫fputc函數(shù)在main.c文件中定義全局變量并且初始化: adcValue、VCCA3、Vrefint、dTemperature在while(1)循環(huán)中調(diào)用以下幾個函數(shù)HAL_ADC_ConfigChannel(hadc1, sConfig)//配置ADC轉(zhuǎn)換參數(shù)HAL_ADC_Start(hadc1);//啟動ADC轉(zhuǎn)換HAL_ADC_PollForConversion(hadc1,10);//等待轉(zhuǎn)換完成adcValue HAL_ADC_GetValue(hadc1);//讀取轉(zhuǎn)換結(jié)果HAL_ADC_Stop(hadc1);計(jì)算溫度值或電壓值打印溫度值或者電壓值printf(VCCA/3 is %.3f V. \r\n,VCCA3)調(diào)試代碼在串口助手中觀察打印出的變量的值。