STM32 HAL庫之DMA模式ADC

  • HAL_ADC_Init()
    用戶自行調用 加載ADC屬性
//ADC句柄聲明 
ADC_HandleTypeDef AdcHandle;

AdcHandle.Instance = ADC1;

AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
AdcHandle.Init.LowPowerAutoWait = DISABLE;
AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;
AdcHandle.Init.Resolution = ADC_RESOLUTION_10B;
AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE;               //掃描模式
AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;              //右對齊
AdcHandle.Init.ContinuousConvMode = DISABLE;                 //不連續轉換
AdcHandle.Init.DiscontinuousConvMode = DISABLE;              //禁止不連續採樣模式
AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;        //軟件觸發
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;//外部觸發規則
AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
AdcHandle.Init.DMAContinuousRequests = DISABLE;              //DMA轉換請求,指定DMA執行單次(當轉換數達標時停止傳送)or連續請求模式;備註:連續模式:
//DMA必須配置爲循環模式,否則當DMA buffer存滿時將觸發溢出; ENABLE or DISABLE
AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;           //選擇數據溢出時的行爲:保存數據或覆蓋數據;這個參數只作用於規則組,包含DMA

//根據傳遞的參數初始化ADC外設 
 if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
 {
     Error_Handler();
 }
  • HAL_ADCEx_Calibration_Start()
    自動校準ADC,調用即可
 //開始校準
 if (HAL_ADCEx_Calibration_Start(&AdcHandle) != HAL_OK)
 {
     Error_Handler();
 }
  • HAL_ADC_ConfigChannel()
    外設控制函數,動態配置外設參數,以下爲配置規則組通道
//ADC通道配置結構聲明 
ADC_ChannelConfTypeDef sConfig;

//頻道配置
//選擇要轉換的通道0
sConfig.Channel = ADC_CHANNEL_VBAT;                         //通道
sConfig.Rank = ADC_RANK_NONE; 
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
{
    Error_Handler();
}

自定義初始化

  • HAL_ADC_MspInit()
    由HAL_ADC_Init()調用,對底層初始化,主要包括時鐘,IO,DMA等,以下函數爲DMA配置
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
	static DMA_HandleTypeDef DmaHandle;
 	//啓用外設和GPIO時鐘
    //使能ADC1 Periph時鐘
    __HAL_RCC_ADC1_CLK_ENABLE();
    //啓用DMA1時鐘
    __HAL_RCC_DMA1_CLK_ENABLE();

	//配置DMA參數
	DmaHandle.Instance = DMA1_Channel1;
    DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
    DmaHandle.Init.MemInc = DMA_MINC_ENABLE;
    DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    DmaHandle.Init.Mode = DMA_CIRCULAR;
    DmaHandle.Init.Priority = DMA_PRIORITY_LOW;


	//取消初始化和初始化DMA以進行新的傳輸
    HAL_DMA_DeInit(&DmaHandle);
    HAL_DMA_Init(&DmaHandle);

    //關聯DMA句柄 
    __HAL_LINKDMA(hadc, DMA_Handle, DmaHandle);

    //DMA輸入數據中斷的NVIC配置
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);


}

中斷

//stm32f0xx_it.c
extern ADC_HandleTypeDef AdcHandle;
extern volatile bool batteryLevelReady;

void DMA1_Channel1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
    batteryLevelReady = true;
}

用戶邏輯

DMA模式,激活ADC外設:

  • HAL_ADC_Start_DMA()
uint32_t batteryLevel;
void startReadBatteryLevel()
{
    //在DMA模式下開始轉換
    if (isSensorsInitialized)
    {
        if (HAL_ADC_Start_DMA(&AdcHandle, &batteryLevel, 1) != HAL_OK)
        {
            Error_Handler();
        }
    }
}
volatile bool batteryLevelReady = false;

uint32_t getBatteryLevel()
{
	batteryLevelReady =  false;
    return batteryLevel;
}

參考

參考:https://www.cnblogs.com/cat-li/p/4982510.html
https://www.cnblogs.com/sovagxa/p/9064746.html

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