標(biāo)題: 關(guān)于STC8G1K08多路ADC電壓采集問題 [打印本頁]

作者: zt997354616    時(shí)間: 2024-3-29 22:04
標(biāo)題: 關(guān)于STC8G1K08多路ADC電壓采集問題
由于項(xiàng)目需要用到5路的ADC采樣,但是我發(fā)現(xiàn)多路通道之間的采樣值會互相影響,是需要在程序上進(jìn)行處理嗎

作者: wulin    時(shí)間: 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;    //計(jì)算輸入電壓mV
        return Vin;
}
作者: xiaobendan001    時(shí)間: 2024-3-30 10:45
怎么個(gè)影響?我用兩個(gè)通道,沒感覺到問題啊
作者: a399288395    時(shí)間: 2024-3-30 14:10
STC還有一個(gè)坑要注意; 由于內(nèi)部電容充電時(shí)間的問題; 采集數(shù)據(jù)切換端口候不能馬上立即采集; 需要稍微等待幾十個(gè)US后等待電容充電穩(wěn)定后再采集;也就是前面采集的幾次數(shù)據(jù)要丟掉;
作者: Y_G_G    時(shí)間: 2024-3-30 14:58
程序只要是對的,就不會有什么影響的,我試有有多加了幾個(gè)不要結(jié)果的ADC,對實(shí)際的結(jié)果并沒有什么改善
一樣的抖動,ADC加個(gè)濾波就可以了
你也可以把你的代碼上傳上來,看一下怎么回事
作者: xiaobendan001    時(shí)間: 2024-3-30 16:02
建議把采樣速度降到較低水平,不要用很高的速度,高速就不怎么穩(wěn)定。
作者: zt997354616    時(shí)間: 2024-3-30 16:34
xiaobendan001 發(fā)表于 2024-3-30 10:45
怎么個(gè)影響?我用兩個(gè)通道,沒感覺到問題啊

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

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


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

丟棄了一次可以嗎,我把ADC的采樣速度設(shè)置得比較快,上面貼了一下程序可以幫忙看一下嗎
作者: zt997354616    時(shí)間: 2024-3-30 16:39
Y_G_G 發(fā)表于 2024-3-30 14:58
程序只要是對的,就不會有什么影響的,我試有有多加了幾個(gè)不要結(jié)果的ADC,對實(shí)際的結(jié)果并沒有什么改善
一 ...

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

void        PCA_config( u8 clk, u8 wide)
{
        CR = 0;   //停止PCA定時(shí)器
        CMOD = (CMOD & ~0x0E) | ((clk & 7) << 1);                // PCA時(shí)鐘選擇, 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;        // 運(yùn)行PCA定時(shí)器
}

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:定時(shí)時(shí)間
/*        1T模式(max=5.9ms):1ms=1000,2ms=500,5ms=200
/*        12T模式(max=71ms):1ms=1000,10ms=100
/*返回值:無
*********************************************/
void Timer0_Config()
{
         
        AUXR |= 0x80;                //定時(shí)器0為1T模式
        TH0 = 0xFD;
        TL0 = 0xE4;
        TMOD &= 0xF0;                //設(shè)置定時(shí)器為模式0,16位自動重裝載
        TR0 = 1;                                //啟動定時(shí)器
        ET0 = 1;                                //打開定時(shí)器中斷
}



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();                        //定時(shí)器0配置,12T模式,time=10ms                                                                                                     
        P_SW2 |= 0x80;                               
    ADCTIM = 0x0a;                              
    P_SW2 &= 0x7f;                                                                //設(shè)置ADC內(nèi)部時(shí)序
    ADCCFG = 0x20;                              //設(shè)置ADC時(shí)鐘為系統(tǒng)時(shí)鐘/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;  //這里同上
                                }
                }                     
        }
}



作者: zt997354616    時(shí)間: 2024-3-30 16:40
xiaobendan001 發(fā)表于 2024-3-30 16:02
建議把采樣速度降到較低水平,不要用很高的速度,高速就不怎么穩(wěn)定。

主要是有一路要用來穩(wěn)住電壓,對adc的采樣速度要求較高
作者: Y_G_G    時(shí)間: 2024-3-31 15:11
你在定時(shí)器中斷中打開了ADC中斷,卻又在主程序中使用了輪詢的方式進(jìn)行ADC
但STC的ADC實(shí)際上只有一個(gè)
而且,在定時(shí)器中斷中,你又有了
ADC_RES = 0;
ADC_RESL = 0;
這兩個(gè)是ADC結(jié)果的寄存器,它會影響Get_ADCResult返回值的

要么是ADC都用中斷的方式,要么就都用輪詢的方式
ADC用輪詢方式的話,ADC對主程序的影響不大,但ADC優(yōu)先權(quán)就不大
ADC用中斷的方式,ADC對主程序影響就很大,因?yàn)槊看蜛DC完成,都要進(jìn)入ADC中斷一次,最終還是要看你整個(gè)程序的需求
作者: coody_sz    時(shí)間: 2024-3-31 19:23
a399288395 發(fā)表于 2024-3-30 14:10
STC還有一個(gè)坑要注意; 由于內(nèi)部電容充電時(shí)間的問題; 采集數(shù)據(jù)切換端口候不能馬上立即采集; 需要稍微等待 ...

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




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