找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2022|回復(fù): 11
打印 上一主題 下一主題
收起左側(cè)

關(guān)于STC8G1K08多路ADC電壓采集問題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1114732 發(fā)表于 2024-3-29 22:04 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
由于項目需要用到5路的ADC采樣,但是我發(fā)現(xiàn)多路通道之間的采樣值會互相影響,是需要在程序上進(jìn)行處理嗎
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:213173 發(fā)表于 2024-3-30 07:13 | 只看該作者
端口模式要設(shè)置高阻,切換通道后丟棄前兩次采樣值
int ADC_rotate(char ch)
{
        int Vin;
        ADC_Read(ch);                 //丟掉兩次檢測
        ADC_Read(ch);
        VADC=ADC_Read(ch);            //取第ch通道ADC結(jié)果
        Vin=VCC*(long)VADC/4096;    //計算輸入電壓mV
        return Vin;
}
回復(fù)

使用道具 舉報

板凳
ID:1109793 發(fā)表于 2024-3-30 10:45 | 只看該作者
怎么個影響?我用兩個通道,沒感覺到問題啊
回復(fù)

使用道具 舉報

地板
ID:230500 發(fā)表于 2024-3-30 14:10 | 只看該作者
STC還有一個坑要注意; 由于內(nèi)部電容充電時間的問題; 采集數(shù)據(jù)切換端口候不能馬上立即采集; 需要稍微等待幾十個US后等待電容充電穩(wěn)定后再采集;也就是前面采集的幾次數(shù)據(jù)要丟掉;
回復(fù)

使用道具 舉報

5#
ID:401564 發(fā)表于 2024-3-30 14:58 | 只看該作者
程序只要是對的,就不會有什么影響的,我試有有多加了幾個不要結(jié)果的ADC,對實際的結(jié)果并沒有什么改善
一樣的抖動,ADC加個濾波就可以了
你也可以把你的代碼上傳上來,看一下怎么回事
回復(fù)

使用道具 舉報

6#
ID:1109793 發(fā)表于 2024-3-30 16:02 | 只看該作者
建議把采樣速度降到較低水平,不要用很高的速度,高速就不怎么穩(wěn)定。
回復(fù)

使用道具 舉報

7#
ID:1114732 發(fā)表于 2024-3-30 16:34 | 只看該作者
xiaobendan001 發(fā)表于 2024-3-30 10:45
怎么個影響?我用兩個通道,沒感覺到問題啊

我貼一下程序麻煩幫我看一下,詳見9樓

                        if((i==6)&&(j<512))
                                {
                                                P37=0;          //這里只有我一上電給通道6低于512的電壓他才會給P37置低,后面給電壓他就沒反應(yīng)
                                }
                        if((i==7)&&(j<512))
                                {
                                                  P37=0;        //同上
                                }

回復(fù)

使用道具 舉報

8#
ID:1114732 發(fā)表于 2024-3-30 16:35 | 只看該作者
a399288395 發(fā)表于 2024-3-30 14:10
STC還有一個坑要注意; 由于內(nèi)部電容充電時間的問題; 采集數(shù)據(jù)切換端口候不能馬上立即采集; 需要稍微等待 ...

丟棄了一次可以嗎,我把ADC的采樣速度設(shè)置得比較快,上面貼了一下程序可以幫忙看一下嗎
回復(fù)

使用道具 舉報

9#
ID:1114732 發(fā)表于 2024-3-30 16:39 | 只看該作者
Y_G_G 發(fā)表于 2024-3-30 14:58
程序只要是對的,就不會有什么影響的,我試有有多加了幾個不要結(jié)果的ADC,對實際的結(jié)果并沒有什么改善
一 ...

好的代碼如下:/*************        PCA配置函數(shù)        **************//*****************************************/

void        PCA_config( u8 clk, u8 wide)
{
        CR = 0;   //停止PCA定時器
        CMOD = (CMOD & ~0x0E) | ((clk & 7) << 1);                // PCA時鐘選擇, 0: 12T,  1: 2T, 2: Timer0溢出率, 3: ECI引腳輸入, 4: 1T,  5: 4T,  6: 6T,  7: 8T
        PCA0_PWM(wide);        //PWM寬度        0: 8位PWM,  1: 7位PWM,  2: 6位PWM,  3: 10位PWM                       
        P_SW1 = (P_SW1 & ~0x30) | 0x00;        // 將PCA/PWM切換到 P5.5(ECI) P3.1(CCP0) P3.3(CCP1) P5.4(CCP2)
        P1n_push_pull(0x02);        //頭文件的宏, P1.1 設(shè)置為推挽輸出                       
        CH = 0;
        CL = 0;
        CR   = 1;        // 運行PCA定時器
}

void        UpdatePwm( u16 pwm_value)
{
                PCA_PWM0 = (PCA_PWM0 & ~0x32) | (u8)((pwm_value >> 4) & 0x30);
                CCAP0H = (u8)pwm_value;
        //        PWM0_NORMAL();               
}
/*****************************************/
/*****************************************/

/*************        PID函數(shù)        ******************/
/*****************************************/

typedef struct PID_Value
{
    int   KP;
    int   KI;
    int          KD;
    int   Inck;
    int   EkSum;
    int   Vref;
    int   Vin;
    int   Ek;
    int   Ek_1;
    int   Ek_2;
    int   dacOutAmp;
    int   Acutual_pidout;
}PID_ValueStr;

PID_ValueStr pidStr;

void PID_initial(void)
{
    pidStr.KP=10;
    pidStr.KI=1;

}

void PID_Caculate()
{                        
    pidStr.Ek=243-VCC ;                                                          
        pidStr.Inck=pidStr.KP*(pidStr.Ek  - pidStr.Ek_1) + pidStr.KI*pidStr.Ek  ;
    pidStr.Ek_2 = pidStr.Ek_1;                                          
    pidStr.Ek_1 = pidStr.Ek;                                                                                                    
        pidStr.dacOutAmp -= pidStr.Inck;                         
        if(pidStr.dacOutAmp<128)                                                          
    pidStr.dacOutAmp = 128;
    if(pidStr.dacOutAmp>243)
    pidStr.dacOutAmp = 243;                                                                                                                  
    pwm_value=pidStr.dacOutAmp;                                                         
}


/*****************************************/
/*****************************************/


/*************        中斷INT0函數(shù)        **********/
/*****************************************/
void INT0_Isr() interrupt 0
{   
         P37=0;
         FLAG=30;                                           
}
/*****************************************/
/*****************************************/
/*************        ADC函數(shù)        **************/
/*************************************/

uint Get_ADCResult(u8 channel)
{       
           ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | channel;
        //delay1us();                        //對ADC_CONTR操作后等待會兒再訪問
        while ((ADC_CONTR & 0x20)==0);
        ADC_CONTR &=~0x20;  
        ADC1_DATA=(ADC_RES<<8)|ADC_RESL;
    return ADC1_DATA;       
}

void ADC_Isr() interrupt 5
{       
        EADC=0;
    ADC_CONTR &= ~0x20;                         //清中斷標(biāo)志
           VCC=(ADC_RES<<8)|ADC_RESL;               
        PID_Caculate();                                                                           
        UpdatePwm(pwm_value);                                                //更新PWM       
}

/*****************************************/
/*****************************************/
/*********************************************
/*函數(shù)名稱:Timer0_Config(u8 mode, u16 time)
/*函數(shù)功能:Timer0配置函數(shù)
/*輸入?yún)?shù):mode:速度模式
/*                                        mode=1, 1T模式; mode=2,12T模式
/*                                        time:定時時間
/*        1T模式(max=5.9ms):1ms=1000,2ms=500,5ms=200
/*        12T模式(max=71ms):1ms=1000,10ms=100
/*返回值:無
*********************************************/
void Timer0_Config()
{
         
        AUXR |= 0x80;                //定時器0為1T模式
        TH0 = 0xFD;
        TL0 = 0xE4;
        TMOD &= 0xF0;                //設(shè)置定時器為模式0,16位自動重裝載
        TR0 = 1;                                //啟動定時器
        ET0 = 1;                                //打開定時器中斷
}



void Timer0() interrupt TIMER0_VECTOR
{       
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | 4;
        while ((ADC_CONTR & 0x20)==0);
        ADC_CONTR &=~0x20;
        EADC=1;       
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | 4;     
}




/*************************************
/*函數(shù)名稱:LED_Init()
/*函數(shù)功能:LED初始化函數(shù)
/*輸入?yún)?shù):無
/*返回值:無
*************************************/
void LED_Init(void)
{
        //P1M1 &= ~(1<<2);        P1M0 |= (1<<2);        //設(shè)置P1.2為推挽輸出
        //P1M1 &= ~(1<<3);        P1M0 |= (1<<3);        //設(shè)置P1.3為推挽輸出
        LED1 = 1;                //初始化LED1
        LED2 = 1;                //初始化LED2
}

/*************************************
/*函數(shù)名稱:LED_Toggle(unsigned char led_id)
/*函數(shù)功能:LED狀態(tài)取反函數(shù)
/*輸入?yún)?shù):LED序號(led_id=1~n)
/*返回值:無
*************************************/
void LED_Toggle(unsigned char led_id)
{
        switch(led_id)
        {
                case 1:
                        LED1 = ~LED1;                //LED1狀態(tài)取反
                        break;
                case 2:
                        LED2 = ~LED2;                //LED2狀態(tài)取反
                        break;
        }
}


/******************** 主函數(shù) **************************/
void main(void)
{
        P0M1 = 0;   P0M0 = 0;   //設(shè)置為準(zhǔn)雙向口
        P1M1 = 0;   P1M0 = 0;   //設(shè)置為準(zhǔn)雙向口
        P2M1 = 0;   P2M0 = 0;   //設(shè)置為準(zhǔn)雙向口
        P3M1 = 0;   P3M0 = 0;   //設(shè)置為準(zhǔn)雙向口
    P1M0 = (P1M0 & ~0xf8) | 0x04; P1M1 = (P1M1 & ~0x04) | 0xf8;           //P1.2推挽輸出 P1.3 P1.4 P1.5 P1.6 P1.7 高阻輸入
    P3M0 |= 0xac; P3M1 &= ~0xac;             //        P3.2 P3.3 P3.5 P3.7  推挽輸出
        PID_initial();
        PCA_config(4,0);
        LED_Init();                                        //LED初始化函數(shù)
        Timer0_Config();                        //定時器0配置,12T模式,time=10ms                                                                                                     
        P_SW2 |= 0x80;                               
    ADCTIM = 0x0a;                              
    P_SW2 &= 0x7f;                                                                //設(shè)置ADC內(nèi)部時序
    ADCCFG = 0x20;                              //設(shè)置ADC時鐘為系統(tǒng)時鐘/2/16
    ADC_CONTR = 0x80;                           //使能ADC模塊
    IT0 = 1;                                    //使能INT0下降沿中斷
    EX0 = 1;                                    //使能INT0中斷
        IPH=0x03;
        IP=0x21;
    EA = 1;                                                                                //允許總中斷       
       
        while(1)
        { u8 i ;
          u16 j ;
                 for(i=5; i<8; i++)
                {
                        Get_ADCResult(i);
                        j=Get_ADCResult(i);
                        if((i==6)&&(j<512))
                                {
                                P37=0;   //主要是這里,只有一開始上電給低于512的電壓他才能給P37置低,如果開始電壓比較高,后續(xù)再給低電壓也不行
                                }
                        if((i==7)&&(j<512))
                                {
                                                  P37=0;  //這里同上
                                }
                }                     
        }
}


回復(fù)

使用道具 舉報

10#
ID:1114732 發(fā)表于 2024-3-30 16:40 | 只看該作者
xiaobendan001 發(fā)表于 2024-3-30 16:02
建議把采樣速度降到較低水平,不要用很高的速度,高速就不怎么穩(wěn)定。

主要是有一路要用來穩(wěn)住電壓,對adc的采樣速度要求較高
回復(fù)

使用道具 舉報

11#
ID:401564 發(fā)表于 2024-3-31 15:11 | 只看該作者
你在定時器中斷中打開了ADC中斷,卻又在主程序中使用了輪詢的方式進(jìn)行ADC
但STC的ADC實際上只有一個
而且,在定時器中斷中,你又有了
ADC_RES = 0;
ADC_RESL = 0;
這兩個是ADC結(jié)果的寄存器,它會影響Get_ADCResult返回值的

要么是ADC都用中斷的方式,要么就都用輪詢的方式
ADC用輪詢方式的話,ADC對主程序的影響不大,但ADC優(yōu)先權(quán)就不大
ADC用中斷的方式,ADC對主程序影響就很大,因為每次ADC完成,都要進(jìn)入ADC中斷一次,最終還是要看你整個程序的需求
回復(fù)

使用道具 舉報

12#
ID:1034262 發(fā)表于 2024-3-31 19:23 | 只看該作者
a399288395 發(fā)表于 2024-3-30 14:10
STC還有一個坑要注意; 由于內(nèi)部電容充電時間的問題; 采集數(shù)據(jù)切換端口候不能馬上立即采集; 需要稍微等待 ...

說法不對,不采樣時是斷開連接的,等多久都沒用。
正確方法是設(shè)置采樣時間,用稍長的采樣時間,一般到3us以上就沒問題了。
或者切換通道后先做一次ADC并丟棄結(jié)果。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表