找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

stc8單片機(jī)ADC切換采樣異常問題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:708541 發(fā)表于 2021-3-22 15:23 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
任意單個通道采樣沒有問題,連續(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)試了一天,我肯定不是程序的問題,我懷疑是芯片的問題了。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:895064 發(fā)表于 2021-3-22 16:06 | 只看該作者
我也懷疑是芯片的問題
回復(fù)

使用道具 舉報

板凳
ID:123289 發(fā)表于 2021-3-22 16:38 | 只看該作者
在AD的硬件中,有一個采樣電容,當(dāng)你下達(dá)采樣命令后,會經(jīng)歷如下的過程:
1、將這個電容與端口連通,并保持若干個時鐘。目的讓電容上得到與端口一樣的電壓。
2、再切斷與端口的連接,防止在進(jìn)行電壓比較時,電壓有波動,影響、絞亂逐次逼近的邏輯。
3、接下來才進(jìn)行真正的AD轉(zhuǎn)換(逐次逼近),需要N個時鐘周期,得到AD值。
所以,采樣時要注意(這是精華):
切換端口后,要過一段時間再下達(dá)采樣命令,因?yàn)閯偳袚Q后,采樣電容上是上一個通道的電壓,需要有一個充放電的過程,才能變?yōu)樾峦ǖ蓝丝谏系碾妷。這一點(diǎn)相當(dāng)重要。!新手一般不會考慮到這一點(diǎn),許多高手也吃它的苦。表現(xiàn)為采樣電壓的數(shù)據(jù)不穩(wěn)定,其實(shí)是部分地受上個通道的電壓“殘余”影響了。

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

讀不透AD采樣的原理,就無法理解采樣不準(zhǔn)的原因!

評分

參與人數(shù) 1黑幣 +5 收起 理由
ax6808 + 5

查看全部評分

回復(fù)

使用道具 舉報

地板
ID:708541 發(fā)表于 2021-3-22 17:08 | 只看該作者
以前STC15系列都不會出現(xiàn)這樣的問題,stc8,往后出的單片機(jī)感覺技術(shù)都不是很成熟,經(jīng)常出現(xiàn)一些奇怪的問題,
回復(fù)

使用道具 舉報

5#
ID:879348 發(fā)表于 2021-3-22 17:20 | 只看該作者
因?yàn)椴蓸颖3蛛娙莸拇嬖?/td>
回復(fù)

使用道具 舉報

6#
ID:1065343 發(fā)表于 2023-3-5 23:59 | 只看該作者
問題解決了嗎?我也遇到同樣的問題
回復(fù)

使用道具 舉報

7#
ID:579397 發(fā)表于 2023-3-6 01:00 | 只看該作者
yzwzfyz 發(fā)表于 2021-3-22 16:38
在AD的硬件中,有一個采樣電容,當(dāng)你下達(dá)采樣命令后,會經(jīng)歷如下的過程:
1、將這個電容與端口連通,并保 ...

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

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

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

回復(fù)

使用道具 舉報

8#
ID:1034262 發(fā)表于 2023-3-6 10:12 | 只看該作者
不是芯片的問題,芯片要有這個問題,根本就沒法面市。
ADC輸入懸空的通道,采樣時,采樣電容沒法充放電,所以看似受上一個通道的影響。
樓主要多了解一下ADC的原理,就不會有此問。
回復(fù)

使用道具 舉報

9#
ID:975054 發(fā)表于 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)換成功。可能是我之前測的內(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位,前面自動補(bǔ)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位,前面自動補(bǔ)0);
    VP55 =(u16)((u32)VCC*(u32)res >>10);        //220524:/1024改右移10位快,注意變量運(yùn)算轉(zhuǎn)換避免溢出錯誤等;                           

    if(CHG==0)                      //5、低電量告警/自動待機(jī); 未充電有效;   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:自動待機(jī);                                                                        
   }                                                                                                                                                   
    else                            //6、充電狀態(tài)指示:4種;   不進(jìn)PD不待機(jī)!  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)充滿保護(hù),全按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次;                                      
   }}}}
}


評分

參與人數(shù) 1黑幣 +60 收起 理由
admin + 60 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

10#
ID:975054 發(fā)表于 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:光控電路檢測點(diǎn)電壓
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)機(jī)ISP/2自動待機(jī)/3充電指示
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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