欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: STC15W408AS 利用bandgap計算VCC電壓不準確的問題 [打印本頁]

作者: samxon    時間: 2025-12-28 16:49
標題: STC15W408AS 利用bandgap計算VCC電壓不準確的問題

STC15W408AS 利用bandgap計算VCC電壓。 我的VCC電壓是5V,但計算出來確實9.3V,請大家幫忙看看代碼問題。謝謝

//初始化ADC
void AdInit()
{       
        P1ASF = 0x00;
        ADC_RES = 0;        ADC_RESL = 0;                                        //清除ADC結果寄存器
        ADC_CONTR = 0x88;
        _nop_();_nop_();
        ADC_CONTR |= 0x08;
        delay_ms(20);                                                                                                //等待ADC穩定
        EADC = 1;                                                                                                 //允許AD轉換中斷
}


unsigned int read_bandgap_voltage(){
        uchar idata *iptr;                                //定義RAM內存區指針
        iptr = ID_ADDR_RAM;
        bandgap=*iptr++;
        bandgap<<=8;
        bandgap+=*iptr;                                                //從內存區讀取BandGap電壓值(單位毫伏)
        return bandgap;
}


void adc_isr() interrupt 5{
                ADC_CONTR &= ~0x10;               
               adc_val=(ADC_RES<<2)|(ADC_RESL);
              VFt=(float)((long)(read_bandgap_voltage()*1024)/adc_val);  
           //VFt的電壓值與實際VCC電壓值相差甚遠,是什么問題引起的。       
               
                                ADC_CONTR = 0x88;
                                _nop_();_nop_();_nop_();_nop_();        //等待四個機器周期
                                while(!(ADC_CONTR&ADC_FLAG));

}

VFt的值是9.3V,

作者: whwteng    時間: 2025-12-29 12:39
添加一個基準電壓比較再采集計算
作者: whwteng    時間: 2025-12-29 12:40
添加一個基準電壓再采樣計算
作者: samxon    時間: 2025-12-29 19:24
經過反復排查
void adc_isr() interrupt 5{
                ADC_CONTR &= ~0x10;               
                     uint vcc_voltage=(float)(5.0*bandgap/adc_val);

     串口打印出來 bandgap是D7, adc_val是02, vcc_voltage結果是十進制24, 為什么vcc_voltate不是十進制537呢。


作者: 188610329    時間: 2025-12-29 20:51
保存在 RAM 的 基準點壓參考值,開機后有可能被改寫,建議從 CODE中讀取。 或者,開機后,優先讀取 RAM中的參考值,再執行其他代碼。
作者: shuiquan3    時間: 2025-12-29 21:55
請教:STC15W408AS如何使用外部基準電壓,接哪個引腳,還是P1口隨便接?
作者: shuiquan3    時間: 2025-12-29 21:57
請教:stc15w408as如何使用外部基準電壓?
作者: TP802    時間: 2025-12-30 08:31
這里提出另外一個問題:計算讀取的電壓時,1024應該為1023,STC手冊中給出的是1024,也是錯誤的。請大家討論。
作者: angmall    時間: 2025-12-30 19:05
shuiquan3 發表于 2025-12-29 21:55
請教:STC15W408AS如何使用外部基準電壓,接哪個引腳,還是P1口隨便接?

A/D 轉換模塊的參考電壓源
STC15 系列單片機的參考電壓源是輸入工作電壓 Vcc,所以一般不用外接參考電壓源。如 7805 的輸
出電壓是 5V,但實際電壓可能是 4.88V 到 4.96V,用戶需要精度比較高的話,可在出廠時將實際測出的
工作電壓值記錄在單片機內部的 EEPROM 里面,以供計算。
如果有些用戶的 Vcc 不固定,如電池供電,電池電壓在 5.3V--4.2V 之間漂移,則 Vcc 不固定,就需
要在 8 路 A/D 轉換的一個通道外接一個穩定的參考電壓源,來計算出此時的工作電壓 Vcc,再計算出其
他幾路 A/D 轉換通道的電壓。如下圖所示,可在 ADC 轉換通道的第二通道外接一個 2.5V( 或 1V,或...)
的基準參考電壓源,由此求出此時的工作電壓 Vcc,再計算出其它幾路 A/D 轉換通道的電壓( 理論依據
是短時間之內, Vcc 不變)。






作者: WL0123    時間: 2026-1-1 21:06
samxon 發表于 2025-12-29 19:24
經過反復排查
void adc_isr() interrupt 5{
                ADC_CONTR &= ~0x10;               

//                當前VCC_mV = 標準電壓mV * 標準電壓BandGap轉換值 / 當前電壓BandGap轉換值
                VCC        = 5000       * (long)BGV5            / BGVx;

作者: Jack315    時間: 2026-1-2 01:14
測量 VCC 的步驟:
① 給定一個比較精確的電源電壓 VCCA ,得到 BandGap (間隙基準源)的 ADC 讀數 BGVA。據此可計算出 BandGap 的基準電壓 VBG 。
② 當電源電壓為 VCCX 時,得到另一個 BandGap 的 ADC 讀數為 BGVX。則 VCCX = BGVX * VBG / BGVA 。

10 位 ADC  的值范圍為:0x000 ~ 0x3FF (十進制:0~1023)。
假設 VCCA = 5.00V,間隙基準源的基準電壓為 VBG = 1.25V,則 BGVA 的值為:1.25V / 5.00V * 1023 = 255.75。
四舍五入得到 256。即此時的 ADC 讀數應為 BGVA = 0x100 (十進制:256)。

假設在待測電源電壓下 BandGap 的 ADC 讀數為 BGVX = 0x266 (十進制:614),
則 VCCX = BGVX * VBG / BGVA = 614 * 1.25 / 256 = 2.998V

【說明】
① 注意到測量 VBG 時,ADC 的量化作用導致了測量誤差:5.00V * 256 / 1023 = 1.251222V 。為提高測量精度,可用不同的 VCCA 進行測量,然后對計算出的 VBG 值求平均作為 VBG 的 “精確” 值。

② 注意到 10位 ADC 的讀數需要三個 Nibble(半字節),比較方便的類型為雙字節的無符號整數(可以定義為 UInt16)。
以上述假設的數據為例:
UInt16 BGVA = 0x0100、UInt16 BGVX = 0x0266、float VBG = 1.25;
float VCCX = (float) BGVX * VBG / (float) BGVA 。
假設要用 UInt16 來表示 VCCX ,可以先將 VCCX 乘以一個適當的常數 (float) C,以保留足夠的輸出精度:
UInt16 Result = (UInt16) (VCCX * C) 。
若最大 VCCA = 5.5V 時,輸出為 0xFFFF,則 C 可取為 65535 / 5.5 = 11915.4545454545 。

作者: samxon    時間: 2026-1-2 17:37
Jack315 發表于 2026-1-2 01:14
測量 VCC 的步驟:
① 給定一個比較精確的電源電壓 VCCA ,得到 BandGap (間隙基準源)的 ADC 讀數 BGVA ...

VCC供電是5V, 以下代碼還是無法獲取到真實電壓值。請大家幫忙看看是什么問題導致的。


void AdInit()
{       
        P1ASF = 0x00;
        ADC_RES = 0;        ADC_RESL = 0;
        CLK_DIV = 0x20;                                                                        
        ADC_CONTR = 0x88;
        _nop_();_nop_();
        ADC_CONTR |= 0x08;
        delay_ms(20);
        EADC = 1;
}

unsigned int read_bandgap_voltage(){
        return (*(unsigned char idata *)ID_ADDR_RAM <<8) |*(unsigned char idata *)(ID_ADDR_RAM + 1);
}

void adc_isr() interrupt 5{

        uint adc_val=(ADC_RES*256+ADC_RESL);
        uint vcc_voltage=5.0*((float)read_bandgap_voltage()/(float)adc_val);

        P1ASF=0x00;
        ADC_CONTR = 0x88|0x00;
        _nop_();_nop_();_nop_();_nop_();        //等待四個機器周期
        while(!(ADC_CONTR&ADC_FLAG));
        ADC_CONTR &=~ADC_FLAG;
}
作者: Jack315    時間: 2026-1-3 11:04
中斷函數 adc_isr() 中:
adc_val 值是多少?
read_bandgap_voltage() 函數的返回值是多少?
最后得到的 vcc_voltage 是多少?

能不能上傳一個 STC15W408AS 的數據手冊,或給個鏈接。
想具體看看 BandGap 和 ADC 相關部分的硬件結構和編程信息。


作者: WL0123    時間: 2026-1-3 11:14
samxon 發表于 2026-1-2 17:37
VCC供電是5V, 以下代碼還是無法獲取到真實電壓值。請大家幫忙看看是什么問題導致的。

測量ADC的第9通道推算VCC電壓計算INV.rar (19.65 KB, 下載次數: 0)




作者: samxon    時間: 2026-1-4 09:43
Jack315 發表于 2026-1-3 11:04
中斷函數 adc_isr() 中:
adc_val 值是多少?
read_bandgap_voltage() 函數的返回值是多少?

串口打印出來, adc_val值是0x02, read_bandgap_voltage()值是0x04D7, 反正最后得到的就不是VCC的真實電壓。謝謝。
作者: samxon    時間: 2026-1-4 12:59
這個讀取BGV 的地址為什么不是0xef ,而是0x0000呢

我定義的地址是#define ID_ADDR_RAM 0xef                                //BandGap地址

#define IAP_ADDRESS 0x0000                                //測試地址

作者: WL0123    時間: 2026-1-4 16:37
發表于 2026-1-4 12:59
這個讀取BGV 的地址為什么不是0xef ,而是0x0000呢

我定義的地址是#define ID_ADDR_RAM 0xef                                //BandG ...

STC15W408AS的EEPROM共有10個扇區,各扇區首地址分別為0x0000、0x0200、0x0400......。BGV就2個字節的數據,只要沒搞錯你愛存哪里都可以。BGV不是憑空來的,必須是此芯片在某特定電源電壓下測得的。這與STC8系列有所不同。STC8系列出廠時已將內部1.19V參考信號源電壓值保存在指定地址:BGV = (int idata *)0xef;,前者保存的是ADC轉換值,后者保存的是電壓值,易混淆。后期處理不當會出錯。
作者: Jack315    時間: 2026-1-5 00:10
samxon 發表于 2026-1-4 09:43
串口打印出來, adc_val值是0x02, read_bandgap_voltage()值是0x04D7, 反正最后得到的就不是VCC的真實電 ...

10-位 ADC 的值范圍為 0x0000 ~ 0x03FF。0x04D7 不是一個有效的 ADC 數據。
說明:
① 數據本身錯誤,或者
② read_bandgap_voltage() 中的代碼有問題。
作者: samxon    時間: 2026-1-5 11:12
WL0123 發表于 2026-1-4 16:37
STC15W408AS的EEPROM共有10個扇區,各扇區首地址分別為0x0000、0x0200、0x0400......。BGV就2個字節的數 ...

STC15W408AS 讀取0xef  的值為0x04D7, 明顯是 1239mv,這個應該怎樣處理。謝謝。


#define ID_ADDR_RAM 0xef                                //BandGap地址
unsigned int read_bandgap_voltage(){
        return (*(unsigned char idata *)ID_ADDR_RAM <<8) |*(unsigned char idata *)(ID_ADDR_RAM + 1);
}
作者: WL0123    時間: 2026-1-5 13:32
samxon 發表于 2026-1-5 11:12
STC15W408AS 讀取0xef  的值為0x04D7, 明顯是 1239mv,這個應該怎樣處理。謝謝。

STC15W408AS 讀取0xef  的值為0x04D7,你憑什么說 明顯是 1239mv。你根據什么理由或資料證明地址0xef 里的數據是內部參考電壓值?STC15W用戶手冊哪里有此說明?官方示例程序也沒有類似應用。不可能憑空找一個數據就能得到正確結果。
作者: Hephaestus    時間: 2026-1-5 21:08
samxon 發表于 2025-12-29 19:24
經過反復排查
void adc_isr() interrupt 5{
                ADC_CONTR &= ~0x10;               

如果read_bandgap_voltage()讀到的0x4d7是Vbg的mV數,那么這句:
(long)(read_bandgap_voltage()*1024)/adc_val);
就是對的,現在的問題是adc_val應該在255左右,檢查下為什么這個值錯的離譜吧!
作者: Jack315    時間: 2026-1-5 22:09
samxon 發表于 2026-1-5 11:12
STC15W408AS 讀取0xef  的值為0x04D7, 明顯是 1239mv,這個應該怎樣處理。謝謝。

假設 0x04D7 (十進制:1239) 是間隙基準源的電壓值 (1239mV),則讀取這個電壓值的代碼可以改成:
  1. float read_bandgap_voltage()
  2. {
  3.                 unsigned int bg_voltage;

  4.                 bg_voltage = *(unsigned char idata *)ID_ADDR_RAM << 8;
  5.                 bg_voltage |= *(unsigned char idata *)(ID_ADDR_RAM + 1);

  6.                 return (float) bg_voltage / 1000.0;
  7. }
復制代碼
這段代碼應該就能得到間隙基準源的電壓值為 1.239V ,與典型值 1.25V 相比,這個值的相對誤差為 0.88%,是個合理的值。

“adc_val 值是 0x02” :這個數據應該是雙字節,所以這個數據是有問題的。假設完整的數據是 adc_val = 0x0102 (十進制:258),則電源電壓的值為:1.239V * 1023 / 258 = 4.9128 V 。
即 adc_val = 0x0102 是在 Vcc = 4.9128V 時,測量間隙基準源電壓所得到到 ADC 讀數。

參考 11# 的說明。



作者: samxon    時間: 2026-1-6 09:13
WL0123 發表于 2026-1-5 13:32
STC15W408AS 讀取0xef  的值為0x04D7,你憑什么說 明顯是 1239mv。你根據什么理由或資料證明地址0xef 里 ...


手冊上的讀取地址





作者: WL0123    時間: 2026-1-6 16:33
samxon 發表于 2026-1-6 09:13
手冊上的讀取地址



作者: hhh402    時間: 2026-1-23 11:21
問題出在:uint adc_val=(ADC_RES*256+ADC_RESL);數據溢出。
要改為:uint adc_val=((uint)ADC_RES*256+ADC_RESL);
作者: 56379075    時間: 2026-1-24 16:01
P1ASF = 0x00;這句有問題,需要ADC的端口要轉成模擬狀態的
作者: samxon    時間: 2026-2-3 09:37
電壓波動的很厲害,是不是切換ADC通道引起的問題

#define IAP_ADDRESS 0xef                                //測試地址

void main()
{
        uchar i;
        P1M0 = 0x00;P1M1 = 0x80;         //P1.7高阻用作ADC輸入
        P3M0 = 0x00;P3M1 = 0x00;
        P5M0 = 0x00;P5M1 = 0x00;       
        InitUart();                      //初始化串口
        InitADC();                       //初始化ADC

        BGV5=IapReadByte(IAP_ADDRESS)<<8|IapReadByte(IAP_ADDRESS+1);//程序開始時讀取EEPROM中保存的BandGap數據               
        /*if(BGV5==0xffff)                 //如果EEPROM中沒有有效數據
        {
                BGV5=0x0100;                  //內部BandGap參考電壓在標準5V VCC的ADC轉換值
                IapEraseSector(IAP_ADDRESS);  //擦除EEPROM
                IapProgramByte(IAP_ADDRESS, BGV5>>8);//寫高8位
                IapProgramByte(IAP_ADDRESS+1, BGV5);//寫低8位
        }*/
       
        while (1)
        {
                P1ASF = 0x00;                 //不設置P1口為模擬口,開通ADC內部第9通道
                Delay_ms(1);
                BGVx=GetADCResult(0);         //讀ADC的內部第9通道
//                當前VCC_mV = 標準電壓mV * 標準電壓BandGap轉換值 / 當前電壓BandGap轉換值
                VCC = 5000*(long)BGV5/BGVx;   //計算當前VCC電壓
                dis_buf[0]=VCC/1000%10+'0';
                dis_buf[1]=VCC/100%10+'0';
                dis_buf[2]=VCC/10%10+'0';
                dis_buf[3]=VCC%10+'0';
                dis_buf[4]=' ';
                P1ASF = 0x80;                 //設置P1.7為模擬口,開通ADC第8通道
                Delay_ms(1);
                VINx=GetADCResult(7);         //讀ADC的第8通道
                VIN=VCC*(long)VINx/1023;      //計算第8通道當前輸入電壓
                dis_buf[5]=VIN/1000%10+'0';
                dis_buf[6]=VIN/100%10+'0';
                dis_buf[7]=VIN/10%10+'0';
                dis_buf[8]=VIN%10+'0';
                dis_buf[9]='\n';
                for(i=0;i<10;i++)
                        SendData(dis_buf);      //串口發送當前VCC電壓和當前輸入電壓
                Delay_ms(1000);
        }
}





作者: WL0123    時間: 2026-2-3 15:09
http://www.raoushi.com/bbs/dpj-56990-1.html
作者: samxon    時間: 2026-2-3 16:16
WL0123 發表于 2026-2-3 15:09
http://www.raoushi.com/bbs/dpj-56990-1.html

串口發送BGV5的值為0x04D9, 換算為電壓為1242mv,與芯片讀取的電壓一致?雌饋響摏]有問題,

但芯片5V vcc供電,但實際串口發送的是4238mv, ADC采集vcc供電的電壓也是4238mv, 請再幫忙解釋一下。

uint idata BGV5 _at_ 0xef;

void main()
{
        uchar i;
        P1M0 = 0x00;P1M1 = 0x80;         //P1.7高阻用作ADC輸入
        P3M0 = 0x00;P3M1 = 0x00;
        P5M0 = 0x00;P5M1 = 0x00;        
        InitUart();                      //初始化串口
        InitADC();                       //初始化ADC

        //BGV5=IapReadByte(IAP_ADDRESS)<<8|IapReadByte(IAP_ADDRESS+1);//程序開始時讀取EEPROM中保存的BandGap數據               
        //BGV5=0x04D9;
        /*if(BGV5==0xffff)                 //如果EEPROM中沒有有效數據
        {
                BGV5=0x0100;                  //內部BandGap參考電壓在標準5V VCC的ADC轉換值
                IapEraseSector(IAP_ADDRESS);  //擦除EEPROM
                IapProgramByte(IAP_ADDRESS, BGV5>>8);//寫高8位
                IapProgramByte(IAP_ADDRESS+1, BGV5);//寫低8位
        }*/
        
        while (1)
        {
                P1ASF = 0x00;                 //不設置P1口為模擬口,開通ADC內部第9通道
                Delay_ms(1);
                BGVx=GetADCResult(0);         //讀ADC的內部第9通道
//                當前VCC_mV = 標準電壓mV * 標準電壓BandGap轉換值 / 當前電壓BandGap轉換值
                VCC = 5000*(long)BGV5/BGVx;   //計算當前VCC電壓
                dis_buf[0]=VCC/1000%10+'0';
                dis_buf[1]=VCC/100%10+'0';
                dis_buf[2]=VCC/10%10+'0';
                dis_buf[3]=VCC%10+'0';
                dis_buf[4]=' ';
                P1ASF = 0x80;                 //設置P1.7為模擬口,開通ADC第8通道
                Delay_ms(1);
                VINx=GetADCResult(7);         //讀ADC的第8通道
                VIN=VCC*(long)VINx/1023;      //計算第8通道當前輸入電壓
                dis_buf[5]=VIN/1000%10+'0';
                dis_buf[6]=VIN/100%10+'0';
                dis_buf[7]=VIN/10%10+'0';
                dis_buf[8]=VIN%10+'0';
                dis_buf[9]='\n';
                for(i=0;i<10;i++)
                        SendData(dis_buf[i ]);      //串口發送當前VCC電壓和當前輸入電壓
//        SendData((BGV5>>8)&0xff);
//        SendData(BGV5&0xff);
                Delay_ms(1000);
        }
}






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