標(biāo)題: stc8單片機ADC切換采樣異常問題 [打印本頁]

作者: as21cxz    時間: 2021-3-22 15:23
標(biāo)題: stc8單片機ADC切換采樣異常問題
任意單個通道采樣沒有問題,連續(xù)切換通道采樣就出現(xiàn)異常,比如我用P1.0和P1.1,這2個腳連續(xù)ADC采樣,P1.0第一次采樣正常,通道++,切換到P1.1采樣,也正常,然后循環(huán)切換到P1.0的時候,P1.0是沒有電壓輸入的,P1.1的輸入3.3V,采樣的結(jié)果直接賦到P1.0里面,意思就是說,P1.1有電壓那直接給P1.0,好像芯片內(nèi)部P1.0和P1.1聯(lián)通了一樣,程序我調(diào)試了一天,我肯定不是程序的問題,我懷疑是芯片的問題了。
作者: 并聯(lián)電阻235    時間: 2021-3-22 16:06
我也懷疑是芯片的問題
作者: yzwzfyz    時間: 2021-3-22 16:38
在AD的硬件中,有一個采樣電容,當(dāng)你下達采樣命令后,會經(jīng)歷如下的過程:
1、將這個電容與端口連通,并保持若干個時鐘。目的讓電容上得到與端口一樣的電壓。
2、再切斷與端口的連接,防止在進行電壓比較時,電壓有波動,影響、絞亂逐次逼近的邏輯。
3、接下來才進行真正的AD轉(zhuǎn)換(逐次逼近),需要N個時鐘周期,得到AD值。
所以,采樣時要注意(這是精華):
切換端口后,要過一段時間再下達采樣命令,因為剛切換后,采樣電容上是上一個通道的電壓,需要有一個充放電的過程,才能變?yōu)樾峦ǖ蓝丝谏系碾妷。這一點相當(dāng)重要。!新手一般不會考慮到這一點,許多高手也吃它的苦。表現(xiàn)為采樣電壓的數(shù)據(jù)不穩(wěn)定,其實是部分地受上個通道的電壓“殘余”影響了。

回到樓主的問題:P1.0是沒有電壓輸入的,即空腳。當(dāng)切換到P1.0之后,采樣電容上的電壓還是上個通道P1.1上的電壓,這時盡管它接改到P1.0上了,但采樣電容被浮空(接在空腳上),也就沒有充放電回路,電壓也就不會有變化了,當(dāng)然……,不必再說了。

讀不透AD采樣的原理,就無法理解采樣不準(zhǔn)的原因!
作者: as21cxz    時間: 2021-3-22 17:08
以前STC15系列都不會出現(xiàn)這樣的問題,stc8,往后出的單片機感覺技術(shù)都不是很成熟,經(jīng)常出現(xiàn)一些奇怪的問題,
作者: wufa1986    時間: 2021-3-22 17:20
因為采樣保持電容的存在
作者: gsls    時間: 2023-3-5 23:59
問題解決了嗎?我也遇到同樣的問題
作者: 405616736    時間: 2023-3-6 01:00
yzwzfyz 發(fā)表于 2021-3-22 16:38
在AD的硬件中,有一個采樣電容,當(dāng)你下達采樣命令后,會經(jīng)歷如下的過程:
1、將這個電容與端口連通,并保 ...

結(jié)合這層的評論,樓主在切換通道采用多少次,看官方的范例,需要丟棄前兩次的結(jié)果。

ADCRead();
  ADCRead();                                  //前兩個數(shù)據(jù)建議丟棄

    res = 0;
    for (i=0; i<8; i++)
    {
        res += ADCRead();                       //讀取8次數(shù)據(jù)
    }
    res >>= 3;                                  //取平均值


作者: coody_sz    時間: 2023-3-6 10:12
不是芯片的問題,芯片要有這個問題,根本就沒法面市。
ADC輸入懸空的通道,采樣時,采樣電容沒法充放電,所以看似受上一個通道的影響。
樓主要多了解一下ADC的原理,就不會有此問。
作者: ax6808    時間: 2023-5-24 17:27
405616736 發(fā)表于 2023-3-6 01:00
結(jié)合這層的評論,樓主在切換通道采用多少次,看官方的范例,需要丟棄前兩次的結(jié)果。

ADCRead();

說起STC15通道ADC范例這個8次平均代碼,當(dāng)然沒有問題。
我之前用20腳STC8G1K08又多出好多腳感覺不爽,近期改8腳STC8G1K08A (練練多腳復(fù)用,體積沒小多少,還厚一些,才便宜幾毛,好手工焊而已)。雙路ADC(因引腳不夠,其中1路直接改用15通道先測MCU供電電壓VCC,再換算電池電壓了,另外一路P55腳復(fù)用,P30P31串口調(diào)試ISPLED復(fù)用等等)。之前2個通道ADC代碼全部放在一起共用不少代碼,只順序切換通道讀取轉(zhuǎn)換一下,沒有刻意中間隔一段時間(之前2個空操作,這次有地方就多加了3個),也沒用8次平均方法,每次都一次順利讀取轉(zhuǎn)換成功?赡苁俏抑皽y的內(nèi)置2個都是電池電壓,比較穩(wěn)定或者精度要求沒那么高吧(這次另外一路測的光敏電阻和1M大電阻分壓值,光敏電阻還并聯(lián)了一個LED,罕見見的。。。。玩唄)!

void BAT()                //VCC電壓ADC15,P55電壓ADC5,低電量告警及充電指示等(早晚光控代碼另列); P3031P55三腳復(fù)用最簡方案用   230523;
{  
    u16 res, *BGV;                  //res:ADC結(jié)果(分辨率); *BGV:指針變量;
    res=0;                                        //         230524:int全改為u16沒有問題(但得同時改!);
    BGV = (u16 idata *)0xef;        //獲取內(nèi)部電壓(1次即可),內(nèi)部1.19V參考源值存放在idata中,EFH高字節(jié)F0H低字節(jié);單位mV;

    P5IE=P5M1=0x20, R=G=b=1;                //1、ADC前:P55允許輸入短暫置高阻,關(guān)彩燈可提高ADC穩(wěn)定準(zhǔn)確度!
                                                    //2. ADC設(shè)置(2句共用):
    ADCCFG = 0x2f;                              //設(shè)置ADC時鐘為系統(tǒng)時鐘/2/16 (含右對齊);
    ADCTIM = 0x3f;                              //設(shè)置ADC內(nèi)部時序:(手冊建議3f,2A~3F);
                                                    //3、ADC15:        VCC和Vbat電壓檢測;                     
    ADC_CONTR = 0xcf;                           //使能ADC模塊,并選擇第15通道,啟動轉(zhuǎn)換3合1;
    _nop_(),_nop_(),_nop_(),_nop_(),_nop_();           //參考手冊2個空操作
    while (!(ADC_CONTR & 0x20));                //查詢ADC完成標(biāo)志
    ADC_CONTR &= ~0x20;                         //清完成標(biāo)志
//  ADC_CONTR &=  0x7F;                                    //ADC轉(zhuǎn)換完即斷電更省電;        (這里后面再一起關(guān));
    res = (ADC_RES << 8) | ADC_RESL;            //讀取ADC結(jié)果 (右對齊:高2位低8位,前面自動補0);
    VCC =(u16)(1024L * *BGV/res);        //先算1次后面再分好;  再處理Vbat修正值+150;
    Vbat=VCC+150L;                                 //

                                                 //4、ADC5: VP55電壓檢測/早晚判斷;                                             
    ADC_CONTR = 0xc5;                           //使能ADC模塊,并選擇第15通道,啟動轉(zhuǎn)換3合1;
    _nop_(),_nop_(),_nop_(),_nop_(),_nop_();           //參考手冊2個空操作
    while (!(ADC_CONTR & 0x20));                //查詢ADC完成標(biāo)志
    ADC_CONTR &= ~0x20;                         //清完成標(biāo)志
    ADC_CONTR &=  0x7F;                                    //ADC轉(zhuǎn)換完即斷電更省電;        (這里后面再一起關(guān));
    res  = (ADC_RES << 8) | ADC_RESL;           //讀取ADC結(jié)果 (右對齊:高2位低8位,前面自動補0);
    VP55 =(u16)((u32)VCC*(u32)res >>10);        //220524:/1024改右移10位快,注意變量運算轉(zhuǎn)換避免溢出錯誤等;                           

    if(CHG==0)                      //5、低電量告警/自動待機; 未充電有效;   230518;               
   {
    if(Vbat>=3438 && Vbat<=3480)                                                 //1-5%告警:紅燈PD2秒快慢閃1遍;同時關(guān)大燈;           
      {W=R=G=b=1, dl_ms(100),R=0,dl_ms(50),R=1,dl_ms(100),R=0,dl_ms(100),R=1;}
    if(Vbat<3438) { W=R=G=b=1, status=2;}                           //<1%燈全滅轉(zhuǎn)狀態(tài)2:自動待機;                                                                        
   }                                                                                                                                                   
    else                            //6、充電狀態(tài)指示:4種;   不進PD不待機!  230516;            
   {status=3, R=G=b=1;                                                        //轉(zhuǎn)狀態(tài)3:充電指示;先滅彩燈;
    if   (Vbat>4132) {G=0,dl_ms( 100),G=1,     dl_ms( 500);}       //   100%:綠燈常閃;  可當(dāng)提醒;  (95%當(dāng)充滿保護,全按0℃,+5mV);
    else                                                                                 
    {if  (Vbat>4077) {G=0,dl_ms(1000),G=1,     dl_ms( 100);}       // > 90%:綠燈亮1秒,    閃1次;
     else                                                                                          
     {if (Vbat>3918) {G=0,dl_ms(1000),G=1, R=0,dl_ms( 100),  R=1;} // > 75%:綠燈亮1秒,紅燈閃1次;         230502 增加1檔;
      else                                                                                   
      {if(Vbat>3716) {R=0,dl_ms(1000),R=1, G=0,dl_ms( 100),  G=1;} // > 50%:紅燈亮1秒,綠燈閃1次;                                             
       else          {R=0,dl_ms(1000),R=1,     dl_ms( 100);}       //<= 50%:紅燈亮1秒,    閃1次;                                      
   }}}}
}



作者: ax6808    時間: 2023-5-25 01:11
ax6808 發(fā)表于 2023-5-24 17:27
說起STC15通道ADC范例這個8次平均代碼,當(dāng)然沒有問題。
我之前用20腳STC8G1K08又多出好多腳感覺不爽,近 ...

串口測試/監(jiān)控打印情況:
   printf("VCC = %4.3f",(f32)VCC /1000),printf("V  \n\n");          
   printf("Vbat= %4.3f",(f32)Vbat/1000),printf("V  \n\n");          
   printf("VP55= %4.3f",(f32)VP55/1000),printf("V  \n\n");          
   printf("VLED= %4.3f",(f32)(VCC-VP55)/1000),printf("V  \n\n");        
   printf("  Kc=%2bu",Kc),printf("  DN=%2bu",DN), printf("  status=%1bu\n",status);

串口助手顯示:
VCC = 3.736V                 //ADC15
Vbat= 3.886V                  // VCC+0.15V 電池防反接二極管5819壓降
VP55= 1.371V                //ADC5:光控電路檢測點電壓
VLED= 2.365V                //大LED燈壓降( VCC-VP55)
Kc= 6  DN= 1  status=0  //Kc:短按組合彩燈模式切換次數(shù)0-10循環(huán)
                                     //DN=0白天/1晚上   
                                     //status=0正常工作/1一鍵關(guān)機ISP/2自動待機/3充電指示




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