標(biāo)題: stm32 ADC實(shí)驗(yàn)(DMA方式) [打印本頁]

作者: wan12345    時(shí)間: 2019-7-12 13:20
標(biāo)題: stm32 ADC實(shí)驗(yàn)(DMA方式)
筆者之前用STM32的ADC外設(shè)通過DMA通道來傳輸數(shù)據(jù),通常有兩種方法,一個(gè)是直接通過DMA通道傳輸數(shù)據(jù),二是通過定時(shí)器觸發(fā)。相較而言,后者在實(shí)際中比較常使用,因?yàn)锳DC讀取傳感器數(shù)據(jù)需要一段時(shí)間,通常我們不會(huì)讓處理器一直讓ADC外設(shè)讀取數(shù)據(jù),而是根據(jù)ADC的讀取時(shí)間和實(shí)際項(xiàng)目所需來使用定時(shí)器觸發(fā),有些傳感器如室內(nèi)溫度我們不需要經(jīng)常讀取,我們可以200ms讀取一次,在STM32處理器中就很方便了,直接通過設(shè)置定時(shí)器觸發(fā)達(dá)到此效果。如果用的處理器沒有這個(gè)功能,我們可以通過定時(shí)器產(chǎn)生的時(shí)隙劃分合適的時(shí)間,在需要的時(shí)間端允許ADC外設(shè)讀取,該做法也是可行的。

下面,列出主要的配置代碼和注意事項(xiàng):

//ADC配置,紅色為注意

void  Adc_Init(void)
{     

ADC_InitTypeDef ADC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //兩個(gè)ADC工作在獨(dú)立模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;            //掃描多通道模式
//    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;        //連續(xù)轉(zhuǎn)換模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        // 定時(shí)器觸發(fā)不使能連續(xù)
    //禁止外部觸發(fā)轉(zhuǎn)換模式,軟件觸發(fā)
    //ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;   
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;    //AD數(shù)據(jù)右對(duì)齊
    ADC_InitStructure.ADC_NbrOfChannel = 2;                    //順序進(jìn)行規(guī)則轉(zhuǎn)換的ADC通道的數(shù)目
    ADC_Init(ADC1, &ADC_InitStructure);

    //規(guī)則采樣通道次序與采樣時(shí)間
        ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5);   
    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5);   

    ADC_TempSensorVrefintCmd(ENABLE);                         //使能內(nèi)部溫度傳感器

    ADC_DMACmd(ADC1, ENABLE);                                 //ADC命令,和DMA關(guān)聯(lián)

    ADC_Cmd(ADC1, ENABLE);                                    //使能ADC      

    ADC_ResetCalibration(ADC1);                                //復(fù)位ADC校準(zhǔn)寄存器
    while(ADC_GetResetCalibrationStatus(ADC1));                //等待校準(zhǔn)寄存器復(fù)位完成

    ADC_StartCalibration(ADC1);                                //開始ADC校準(zhǔn)
    while(ADC_GetCalibrationStatus(ADC1));                    //等待校準(zhǔn)完成

    //ADC_SoftwareStartConvCmd(ADC1, ENABLE);                    //注釋掉軟件啟動(dòng)AD轉(zhuǎn)換
    ADC_ExternalTrigConvCmd(ADC1, ENABLE);  //使能外部定時(shí)器觸發(fā)  
}   

//DMA配置

void MYDMA_Config(void)
{

          DMA_InitTypeDef  DMA_InitStruct;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE );

      //DMA init;  Using DMA1 channel 1
      DMA_DeInit(DMA1_Channel1);                                //復(fù)位DMA1的第1通道
      DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;    //DMA對(duì)應(yīng)的外設(shè)基地址
      DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //轉(zhuǎn)換結(jié)果16bits
      DMA_InitStruct.DMA_MemoryBaseAddr = (u32)ADC_TempValue;
      DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;           //DMA的轉(zhuǎn)換模式是SRC模式,外設(shè)to內(nèi)存
      DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                 //M2M模式禁止,memory to memory
      DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //DMA搬運(yùn)的數(shù)據(jù)16bits

      //接收一次數(shù)據(jù)后,目標(biāo)內(nèi)存地址后移,用來采集多個(gè)數(shù)據(jù)的
      DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    //接收一次數(shù)據(jù)后,設(shè)備地址是否后移
      DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

      //轉(zhuǎn)換模式:常用循環(huán)緩存模式。如果M2M開啟了,則這個(gè)模式失效
      //另一種是Normal模式:不循環(huán),僅一次DMA
      //DMA_InitStruct.DMA_Mode  = DMA_Mode_Circular;
    DMA_InitStruct.DMA_Mode  = DMA_Mode_Normal;

      DMA_InitStruct.DMA_Priority = DMA_Priority_High;             //DMA優(yōu)先級(jí),高
      DMA_InitStruct.DMA_BufferSize = 8;                          //DMA緩存大小
      DMA_Init(DMA1_Channel1,&DMA_InitStruct);

        DMA_ClearITPendingBit(DMA1_IT_TC1);
        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                //開啟DMA1CH1中斷

       DMA_Cmd(DMA1_Channel1, ENABLE);
}

//定時(shí)器配置,設(shè)置想要的觸發(fā)頻率

void TIM2_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //時(shí)鐘使能

    //定時(shí)器TIM3初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值   
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計(jì)數(shù)模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1000;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    //TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能指定的TIM2中斷,允許更新中斷  不需要中斷。是用定時(shí)器的PWM觸發(fā)
    TIM_OC2Init(TIM2, & TIM_OCInitStructure);   
    //中斷優(yōu)先級(jí)NVIC設(shè)置
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中斷
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占優(yōu)先級(jí)0級(jí)
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //從優(yōu)先級(jí)3級(jí)
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    TIM_Cmd(TIM2, ENABLE);  //使能TIMx                     
}

//中斷優(yōu)先級(jí)配置

   void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //優(yōu)先級(jí)分組4,所有位均用于搶占優(yōu)先級(jí)

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);






作者: 一夢(mèng)紅塵    時(shí)間: 2019-7-13 21:11
不錯(cuò),寫的挺詳細(xì)




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1