目標
使用STM32CubeMX工具,配置ADC相關參數,實現在STM32H743單片機上獲取ADC多通道電壓值。共14個ADC引腳,ADC2有5個,ADC3有9個,全部設置單通道
ADC引腳
PF3 |
PF4 |
PF5 |
PF10 |
PC0 |
PC2 |
PC3 |
PH2 |
PH3 |
PA3 |
PB0 |
PB1 |
PA4 |
PA5 |
PA6 |
?STM32cubeMX配置ADC
ADC2配置5個模擬輸入IO,多通道輪詢,配置各通道參數,使能中斷
ADC3配置9個模擬輸入IO,多通道輪詢,配置各通道參數,使能中斷
??時鐘頻率配置
在處理ADC時發現ADC時鐘配置需要處理,可能默認即可,這里試了下是沒問題的,一開始使用的HSE作為ADC時鐘,導致無法獲取ADC參數。在ADC3的屬性配置中,Resolution對應12位分辨率有可能錯誤,如果有問題可以嘗試加大改為16位分辨率,不過改動分辨率之后,在代碼中就需要修改對應的算法,即12位算法(電壓值= adc值*參考電壓/2的12次方-1),16位算法(電壓值= adc值*參考電壓/2的16次方-1)。
?代碼
啟動adc轉換前必須先校準adc,在HAL_ADC_ConvCpltCallback中斷回調函數中,處理對應ADC的代碼,由于HAL_ADC_Start_IT調用后會一直不間斷輪詢,通過HAL_ADC_GetValue函數可直接獲取ADC值,HAL_ADC_Stop_IT函數作用關閉當前ADC轉換。
#define ADC2_CHANNELS 5
#define ADC3_CHANNELS 9uint16_t adc2_values[ADC2_CHANNELS];
uint16_t adc3_values[ADC3_CHANNELS];
volatile uint8_t adc_ready = 0; // 數據就緒標志位void Start_ADC2_DMA(void) {/* 初始化后校準ADC */HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); // 執行ADC校準/* 啟動ADC連續轉換(不間斷輪詢) */HAL_ADC_Start_IT(&hadc2);
}void Start_ADC3_DMA(void) {/* 初始化后校準ADC */HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); // 執行ADC校準/* 啟動ADC連續轉換(不間斷輪詢) */HAL_ADC_Start_IT(&hadc3);
}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {if (hadc->Instance == ADC2) // 確認是ADC2的轉換完成{for (int i = 0; i < ADC2_CHANNELS; i++) {adc2_values[i] = HAL_ADC_GetValue(&hadc2); // 讀取轉換結果
// HAL_ADC_PollForConversion(&hadc2, 100);}adc_ready |= 0x01; // 標記ADC2數據就緒HAL_ADC_Stop_IT(&hadc2);} else if (hadc->Instance == ADC3) // 確認是ADC3的轉換完成{for (int i = 0; i < ADC3_CHANNELS; i++) {adc3_values[i] = HAL_ADC_GetValue(&hadc3); // 讀取轉換結果
// HAL_ADC_PollForConversion(&hadc3, 100);}adc_ready |= 0x02; // 標記ADC3數據就緒HAL_ADC_Stop_IT(&hadc3);}
}
?AdcTask線程任務當ADC2和ADC3都進行轉換之后,在當前線程中處理所有ADC數值并轉換為電壓值輸出打印,結束后清除標志位,等待下次轉換觸發。該線程使用最小棧內存大小128Words。
void AdcTask(void *argument)
{/* USER CODE BEGIN AdcTask */Start_ADC2_DMA();Start_ADC3_DMA();int i = 0;float voltage;/* Infinite loop */for (;;) {if (adc_ready == 0x03) { // 等待兩組ADC數據就緒/* 打印ADC2數據 */for (i = 0; i < ADC2_CHANNELS; i++) {voltage = adc2_values[i] * 3.3f / 4095.0f;printf("ADC2[%d] = %d.%dV\r\n", i, (uint32_t) voltage,(uint32_t) (voltage * 100) % 100);}printf("\n");/* 打印ADC3數據 */for (i = 0; i < ADC3_CHANNELS; i++) {voltage = adc3_values[i] * 3.3f / 4095.0f;printf("ADC3[%d] = %d.%dV\r\n", i, (uint32_t) voltage,(uint32_t) (voltage * 100) % 100);}printf("\n\n");adc_ready = 0; // 清除標志位}osDelay(10);}/* USER CODE END AdcTask */
}
共勉!!!