ADC多路采樣與穩(wěn)定顯示

LED數(shù)碼管或者LCD12864等顯示器在顯示溫度采樣值時(shí)檩奠,需要的是穩(wěn)定的能反映溫度實(shí)際變化的顯示效果。ADC采樣頻率快笆凌,直接采樣輸出的值往往有不小的跳變,這時(shí)候需要對(duì)其數(shù)據(jù)做一些數(shù)字濾波處理送悔。常用的方法有:平均值法爪模、多次采樣用冒泡法取中間一段數(shù)值法、平滑平均線法屋灌。冒泡法處理時(shí)間太長(zhǎng),這里主要用了平均值和平滑平均線兩種方法一起處理祠丝。

一除嘹、算法部分


平滑平均線法可解決一般均值法的欠靈敏和滯后性,同時(shí)濾除毛刺叠蝇。用此法對(duì)ADC采集的數(shù)據(jù)進(jìn)行ADC濾波后年缎,在LCD12864上顯示穩(wěn)定。

具體做法如下:

  1. 在一個(gè)ADC通道上采集多次单芜,獲得采樣平均值a蜕该,用a初始化含有假定100個(gè)數(shù)據(jù)的數(shù)組b[100]中所有的數(shù)據(jù)(這樣b[]數(shù)組的平均值就是a)缓溅;
  2. 后續(xù)每次運(yùn)行一次ADC采樣都會(huì)得到一個(gè)新的采樣平均值A(chǔ),同時(shí)把數(shù)組b的數(shù)據(jù)左移(b[0]=b[1]~~~b[98]=b[99]),然后把A的值賦值給b[99]淤齐;
  3. 如此每次運(yùn)行一次采樣就會(huì)平滑的更新一次數(shù)組b的平均值B袜匿,也就得到了數(shù)字濾波后的平滑平均值B,平均值B就可以拿去做顯示祭务,效果穩(wěn)定;
  4. 實(shí)際程序處理中是:第一次得到的采樣平均值A(chǔ)0賦值給b[0]义锥,如此順序,第100次采樣得到的平均值A(chǔ)99賦值給b[99]赂鲤,之后又重新依次更新b[0]到b[99]的值柱恤,如此循環(huán),這樣做可以減少運(yùn)算量泡孩,同時(shí)達(dá)到左移的效果

平滑平均值代碼

/**
  * @brief  ADC采樣所得到的溫度
  * @param None
  * @retval : None
  */
void ADC1_Tempera(void)
{
    u32 i,k,m,n;
    static u32 ValueCount;
    for(i=0;i<ADC_ChannelCount;i++)
    {
        /*
        *@平均值濾波
        */
        ValueCount=0;
        for(k=0;k<ADC1_Count;k++)//取中間的100次值(ADC1_Count)
        {
            ValueCount+=ADGetValue[k][i];
            ADC_Filter[i]=(ValueCount/ADC1_Count);//求取一個(gè)ADC通道的平均值
        }
        if(Tflag==0)
        {
            for(n=0;n<SmoothNum;n++)
            {
                ADC_SmoothFilter[i][n]=ADC_Filter[i];//獲得第一次平滑值
            }
            ADC_SmoothCount[i]=ADC_Filter[i];//獲取第一次平滑平均值線
        }
        /*
        *@平滑濾波
        */
        if(Tflag==1)
        {
            ADC_SmoothFilter[i][Smoth_Num[i]]=ADC_Filter[i];//把數(shù)值循環(huán)放置
            Smoth_Num[i]++;
            if(Smoth_Num[i]==SmoothNum)
                Smoth_Num[i]=0;
            for(n=0;n<SmoothNum;n++)//平滑濾波
            {
                ADC_SmoothCount[i] += ADC_SmoothFilter[i][n];
            }
            ADC_SmoothCount[i]=(ADC_SmoothCount[i]/SmoothNum);//獲取平滑平均值線
        }
    }
    for(m=0;m<3;m++)
    {
        TMonitor[m]=(((2361*ADC_SmoothCount[2*m])/(ADC_SmoothCount[2*m+1])-2597)+TemperaSet[m+4]);//已經(jīng)擴(kuò)大10倍的值轉(zhuǎn)化為溫度數(shù)據(jù),低溫,高溫,環(huán)境溫度 TemperaSet[m+4]為溫度補(bǔ)償系數(shù)
        if(Tflag==0)
            TMonitorDis[m]=TMonitor[m];
        /*
        *@顯示處理緩慢變化
        */
        if(TMonitorDis[m]<(TMonitor[m]-1))
            TMonitorDis[m] += 1;
        if(TMonitorDis[m]>(TMonitor[m]+1))
            TMonitorDis[m] -= 1;
    }
    Tflag=1;
}

代碼注解

  • ADC_ChannelCount為采樣通道數(shù)仑鸥,其值為6变屁,表示ADC1有6個(gè)采樣通道。
  • ADC1_Count為每一個(gè)通道在執(zhí)行一次采樣函數(shù)中需要采樣的次數(shù),此值為100摄职。
  • ADGetValue[ADC1_Count][ADC_ChannelCount]數(shù)組內(nèi)存中存儲(chǔ)的是6個(gè)通道中每個(gè)通道的100個(gè)數(shù)據(jù),即每執(zhí)行一次函數(shù)void ADC1_Tempera(void)就更新一次這段內(nèi)存的所有數(shù)據(jù)蛔垢。
  • 批量采樣工作過(guò)程是:定時(shí)器觸發(fā)一次后依次采樣通道(1-2-3-4-5-6)迫悠,第二次定時(shí)器觸發(fā)后依次采樣通道(1-2-3-4-5-6),如此連續(xù)轉(zhuǎn)換艺玲,循環(huán)掃描鞠抑;所以要想每個(gè)通道都采樣100次,那么就需要觸發(fā)轉(zhuǎn)換100次秒梳,這樣定義一段內(nèi)存存儲(chǔ)數(shù)據(jù)的數(shù)組就應(yīng)該是ADGetValue[100][6],這樣在i=0~99情況下100個(gè)數(shù)據(jù)ADGetValue[i][0]表示為通道1在采樣了100次后所得到的數(shù)據(jù)酪碘。

ADC通道配置


DMA模式配置要點(diǎn)

  • STM32的ADC1作為DMA的外設(shè)源兴垦,其地址為16位,如果變量值不是16位那么所得到的數(shù)據(jù)會(huì)混亂滑进,但是DMA配置里是32位,所以需要強(qiáng)制轉(zhuǎn)換為32位阴汇。
vu16 ADGetValue[][];//AD采樣值,ADC_ChannelCount個(gè)通道,每個(gè)通道采樣ADC1_Count次
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADGetValue;//設(shè)置DMA內(nèi)存地址节槐,ADC轉(zhuǎn)換結(jié)果直接放入該地址
  • 使用定時(shí)器外部觸發(fā)轉(zhuǎn)換,ADC六個(gè)通道采樣哥倔,循環(huán)采樣模式揍庄、連續(xù)轉(zhuǎn)換。
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;      //使用獨(dú)立模式沃测,掃描模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;            //循環(huán)掃描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;      //連續(xù)轉(zhuǎn)換模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //外部定時(shí)器觸發(fā)轉(zhuǎn)換

ADC配置代碼

/**
  * @brief  配置采樣通道端口 使能GPIO時(shí)鐘    設(shè)置ADC采樣PA0端口信號(hào)
  * @param None
  * @retval : None
  */
void ADC1_GPIO_Config(void)
{ 
    GPIO_InitTypeDef ADC_PORT;    
    RCC_APB2PeriphClockCmd(ADC_ClK, ENABLE);      
    ADC_PORT.GPIO_Pin = ADC_Pin;                //ADC引腳選擇,6個(gè)通道
    ADC_PORT.GPIO_Mode = GPIO_Mode_AIN;         //GPIO設(shè)置為模擬輸入
    GPIO_Init(ADC_CONTROL, &ADC_PORT);   
}
/**
  * @brief  配置ADC1的工作模式為DMA模式
  * @param None
  * @retval : None
  */
 void ADC1_Mode_Config(void)
 {
    ADC_InitTypeDef ADC_InitStructure;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);    //使能ADC1時(shí)鐘 
    /* ADC1 configuration */
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;      //使用獨(dú)立模式食茎,掃描模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;            //循環(huán)掃描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;      //連續(xù)轉(zhuǎn)換模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //外部定時(shí)器觸發(fā)轉(zhuǎn)換
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//數(shù)據(jù)右對(duì)齊
    ADC_InitStructure.ADC_NbrOfChannel = ADC_ChannelCount;  //有ADC_ChannelCount個(gè)轉(zhuǎn)換通道
    ADC_Init(ADC1, &ADC_InitStructure);
    /* 以下為配置通道數(shù)總共6路,分別是AD10,AD11,AD12,AD13,AD14,AD15 */
    /* ADC1 regular channel10 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); //通道10,作為第1個(gè)采樣目標(biāo),采樣周期239.5個(gè)時(shí)鐘周期
    /* ADC1 regular channel11 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5); //通道11,作為第2個(gè)采樣目標(biāo),采樣周期55.5個(gè)時(shí)鐘周期
    /* ADC1 regular channel12 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_55Cycles5); //通道12,作為第3個(gè)采樣目標(biāo),采樣周期55.5個(gè)時(shí)鐘周期
    /* ADC1 regular channel13 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_55Cycles5); //通道13,作為第4個(gè)采樣目標(biāo),采樣周期55.5個(gè)時(shí)鐘周期
    /* ADC1 regular channel14 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_55Cycles5); //通道14,作為第5個(gè)采樣目標(biāo),采樣周期55.5個(gè)時(shí)鐘周期
    /* ADC1 regular channel15 configuration */ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_55Cycles5); //通道15,作為第6個(gè)采樣目標(biāo),采樣周期55.5個(gè)時(shí)鐘周期

    /* Enable ADC1 DMA */
    ADC_DMACmd(ADC1, ENABLE);    //使能ADC的DMA
    /*使能ADC1外部觸發(fā)*/
    ADC_ExternalTrigConvCmd(ADC1,ENABLE);
    /* Enable ADC1 */
    ADC_Cmd(ADC1, ENABLE); //使能ADC1

    /* Enable ADC1 reset calibaration register */   
    ADC_ResetCalibration(ADC1);
    /* Check the end of ADC1 reset calibration register */
    while(ADC_GetResetCalibrationStatus(ADC1));

    /* Start ADC1 calibaration */
    ADC_StartCalibration(ADC1);
    /* Check the end of ADC1 calibration */
    while(ADC_GetCalibrationStatus(ADC1));
     
    /* Start ADC1 Software Conversion */ 
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);  //開(kāi)始轉(zhuǎn)換
    
}
/**
  * @brief  配置DMA
  * @param None
  * @retval : None
  */
 void DMA_Config(void)
 {
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA1時(shí)鐘
    /* DMA1 channel1 configuration */
    DMA_DeInit(DMA1_Channel1);  //指定DMA1通道1
    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//設(shè)置DMA外設(shè)地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADGetValue;//設(shè)置DMA內(nèi)存地址附迷,ADC轉(zhuǎn)換結(jié)果直接放入該地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外設(shè)設(shè)置為數(shù)據(jù)傳輸?shù)膩?lái)源
    DMA_InitStructure.DMA_BufferSize = (ADC_ChannelCount* ADC1_Count);  //DMA緩沖區(qū)設(shè)置為ADC_ChannelCount* ADC1_Count,有6個(gè)通道哎媚;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外設(shè)地址不增加
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//內(nèi)存地址增加
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外設(shè)源的數(shù)據(jù)寬度半字,ADC1_DR的值16位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循環(huán)模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    /* Enable DMA channel1 */
    DMA_Cmd(DMA1_Channel1, ENABLE);  //使能DMA通道
    //DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //使能DMA傳輸完成中斷 
}

/**
  * @brief  初始化ADC1
  * @param None
  * @retval : None
  */
void ADC1_Init(void)
{
    ADC1_GPIO_Config();
    ADC1_Mode_Config();
    DMA_Config();
    TIM1_Mode_Config();//開(kāi)啟定時(shí)器1抄伍,產(chǎn)生PWN1外部觸發(fā)源
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市攀甚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秋度,老刑警劉巖荚斯,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異滥壕,居然都是意外死亡兽泣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門唠倦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稠鼻,“玉大人,你說(shuō)我怎么就攤上這事候齿。” “怎么了怨咪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵润匙,是天一觀的道長(zhǎng)唉匾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)厂财,這世上最難降的妖魔是什么峡懈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮荚恶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谒撼。我一直安慰自己,他們只是感情好抵皱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布辩蛋。 她就那樣靜靜地躺著,像睡著了一般伤为。 火紅的嫁衣襯著肌膚如雪樱蛤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天爽醋,我揣著相機(jī)與錄音便脊,去河邊找鬼。 笑死哪痰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跷睦。 我是一名探鬼主播肋演,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蜕乡!你這毒婦竟也來(lái)了梗夸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤辛块,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后憨降,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡士嚎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年悔叽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笨蚁。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趟庄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奋单,到底是詐尸還是另有隱情猫十,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布贷笛,位于F島的核電站宙项,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏尤筐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奖磁。 院中可真熱鬧,春花似錦秕狰、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挠羔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間破加,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工合是, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锭环,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓荔烧,卻偏偏與公主長(zhǎng)得像汽久,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臀稚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容