migao 发表于 2025-6-16 15:35:57

用STC8H1K08测量电池电压,数据无变化. | 已搞定

    我用用STC8H1K08测量电池电压,输入电压发生变化,但读取的数据无变化.:
1.主芯片为 STC8H1K08 TSSOP 20封装
2.P1.1为 VBAT_ADC输入口
3.P3.1为RXD,P3.0为RXD
    下面是代码:

voidADCInit(void)
{
      Enable_XFR();
//端口数字信号输入使能控制寄存器 PxIE
//PxIE 0:禁止数字信号输入。若 I/O被当作比较器输入口、ADC 输入口或者触摸按键输入口等模拟口时,
//                进入时钟停振模式前,必须设置为 0,否则会有额外的耗电。
//PxIE 1:使能数字信号输入。若 I/O被当作数字口时,必须设置为 1,否 MCU无法读取外部端口的电平。
//      P1IE &= 0xFD;      //1: 使能数字信号输入,1.1作为ADC输入,置0
      P1IE |= 0xFF;      //1: 使能数字信号输入      
      P3IE |= 0x03;      //,3.1/3.0作为RX/TX输入输出口
      

      P1INTE |= 0x02;      //1:使能 Pn.x 口中断功能
      P1INTF &= 0xFD;      //0:中断请求标志位需软件清 0

      P3INTE |= 0x03;      //1:使能 Pn.x 口中断功能
      P3INTF &= 0xFC;      //中断请求标志位需软件清 0


//--------------------------------------------------------
//--ADC时序控制寄存器
//----------------------------------------------------------------
//--|符号|地址 |    B7   |B6|B5| B4B3B2B1B0 |
//--|--------|-------|---------|-------------|--------------------|
//--| ADCTIM | FEA8H | CSSETUP | CSHOLD |    SMPDUTY    |
//----------------------------------------------------------------|
      ADCTIM = 0x3D;// 0b001 1 1101;      //30设置 ADC 内部时序

      Disable_XFR();

//SPEED:设置 ADC 工作时钟频率{FADC=SYSclk/2/(SPEED+1)}         
      ADCCFG = 0x0F;      //SYSclk/2/16
//RESFMT:ADC 转换结果格式控制位
//1:转换结果右对齐。ADC_RES 保存结果的高 2位,ADC_RESL 保存结果的低 8 位
      ADCCFG |= 0x20;
      
//ADC控制寄存器
//-------------------------------------------------------------------------------------
//-|    符号   | 地址 |      B7   |   B6    |   B5   |   B4    | B3B2B1B0 |
//-|-----------|------|-----------|-----------|----------|-----------|----------------|
//-| ADC_CONTR |BCH | ADC_POWER | ADC_START | ADC_FLAG | ADC_EPWMT |ADC_CHS|
//-|-----------------------------------------------------------------------------------
//- ADC_FLAG:ADC转换完成中断请求标志。需要软件清零。         
      ADC_CONTR &= 0xDF;      //ADC_FLAG:ADC转换完成中断请求标志。需要软件清零。


      ADC_CONTR |= 0x01;                //0001,开启P1.1 VBAT_ACD转换口
      ADC_CONTR &= 0xF1;
      
//ADC_POWER:ADC 电源控制位
//0:关闭 ADC 电源
//1:打开 ADC 电源。
//建议进入空闲模式和掉电模式前将 ADC 电源关闭,以降低功耗
      OpenPowerADC();      //1:打开 ADC 电源。
//ADC_START:ADC 转换启动控制位。写入 1 后开始 ADC 转换,转换完成后硬件自动将此位清零。
//0:无影响。即使 ADC 已经开始转换工作,写 0也不会停止 A/D转换。
//1:开始 ADC 转换,转换完成后硬件自动将此位清零。

//      OpenADCStart();

//EADC:A/D转换中断允许位。
//0:禁止 A/D转换中断
//1:允许 A/D转换中断
      IE |= 0x20;      //1:允许 A/D转换中断
}



void ADCChange(void)
{
      if(AllFlag.Flag.ADC_Change_Stop_Flag ==0)
      {
                ADCValue = 0;
                if((ADC_CONTR & 0x0F) == 0x0F)
                {
                        DBG_PRINTF(" -----VBAT_ACD bigan: ");

                        ADC_CONTR |= 0x01;                //0001,开启P1.1 VBAT_ACD转换口
                        ADC_CONTR &= 0xF1;
      }
      else //if((ADC_CONTR & 0x0F) == 0x0F)
      {
                        DBG_PRINTF("+++++ VBAT_ACD OK: ");
                        ADC_CONTR |= 0x0F;
                //      ADC_CONTR &=0xFC;
      }
                AllFlag.Flag.ADC_Change_Stop_Flag = 1;
                ADCChargeTime = 0;
                ADC_CONTR &= 0xDF;      //ADC_FLAG:ADC转换完成中断请求标志需要软件清零
                OpenADCStart();
      }
      else if(ADCChargeTime > TimeParameter50ms)   // 50ms
      {
                ADCChargeTime = 0;
                ADC_CONTR &= 0xDF;
                OpenADCStart();
      }
}


void ADCChargeFunction(void)
{
      unsigned char i;
//      unsigned int temp=1025;
      ADCChange();
      if(AllFlag.Flag.ADC_Change_Finish_Flag)
      {//0xEFF0 = 0x0004A3F7
      //      if((ADC_CONTR & 0x0F) == 0x0C)
                if((ADC_CONTR & 0x0F) == 0x0F)
                {//0x0C Bat VBAT
                        ADCBatValue = ADCValue;
                //      ADCBatValue = ADCValue;
                //      LEDBatValue = ADCBatValue;
                        DBG_PRINTF("BAT: %d\n",ADCValue);
                }
                else if((ADC_CONTR & 0x0F) == 0x01)
                {//0x0E Dat DC_DAT
                        DCDatValue = ADCValue;
                  DBG_PRINTF("DAT: %d\n",ADCValue);
                        if(DCDatValue > DC_DAT_Value)
                        {
                              AllFlag.Flag.DC_DAT_Value_Flag = 1;
                              AllFlag.Flag.INT3_ISR_Flag = 1;
                        }
                        else
                        {
                              AllFlag.Flag.DC_DAT_Value_Flag = 0;
                              AllFlag.Flag.INT3_ISR_Flag = 0;
                        //      CloseAllLED();
                        }
                }
                if(ADCValueTimes >= sizeof(ADCBatValue)/sizeof(unsigned int))
                {
                //      for(i=0;i<ADCValueTimes;i++)
                //                temp = temp <= ADCBatValue ? temp : ADCBatValue;
                        for(i=0;i<(ADCValueTimes-1);i++)
                        {
                              ADCBatValue += ADCBatValue;
                        }
                //      ADCBatValue -=temp;
                        LEDBatValue = ADCBatValue/ADCValueTimes;
                printf("LEDBatValue :%d \n",LEDBatValue);
                        

                        ADCValueTimes = 0;
                }
                AllFlag.Flag.ADC_Change_Finish_Flag = 0;
//                  DBG_PRINTF("00000AllFlag.Flag.ADC_Change_Finish_Flag =: %d\n",AllFlag.Flag.ADC_Change_Finish_Flag);
                AllFlag.Flag.ADC_Change_Stop_Flag = 0;
      }
}



国芯人工智能 发表于 2025-6-16 15:38:00

对于使用STC8H1K08测量电池电压,若数据无变化但输入电压发生变化,可能是因为输入电压的范围不足导致ADC无法准确测量。以下是一些可能的解决方案:

1. 检查ADC的输入电压范围:
   STC8H1K08的ADC测量精度取决于其输入电压范围。建议确保输入电压的范围足够大,以覆盖电池电压的范围(通常在0.4V至3.3V)。如果输入电压范围过小,可能需要调整ADC的配置,例如调整内部的电阻或增加适当的安全保护电路。

2. 检查ADC的输入端口配置:
   检查PxIE和P3IE的设置,确保它们正确配置为使能数字信号输入。PxIE设为1表示使能,P3IE设为1表示使能RX/TX端口。

3. 检查ADC内部电路:
   确保ADC内部电路的电阻匹配和电源稳定。电源可能不稳定或电阻不匹配可能导致输入信号无法准确捕获。

4. 检查ADC的时序控制寄存器:
   确保ADC的时序控制寄存器PxIE和P3IE正确设置为1,以确保ADC能够正确捕获电压信号。

5. 检查ADC的中断功能:
   检查PxINTE和P3INTE的设置,确保中断功能正确工作。中断请求标志位需软件清0。

6. 调试ADC的内部电路:
   如果以上步骤均未解决问题,可能需要调试ADC内部电路,检查引脚连接是否正确,以及任何潜在的损坏或短路。

7. 使用电源保护:
   如果电源不稳定,使用电源保护电路(如DC保护、PMOS或FET)可能有助于提高ADC的稳定性。

8. 检查外部电源的稳定性:
   若外部电源不稳定,可能导致ADC无法正常工作,进而影响电压测量结果。

通过以上步骤,您可以逐步排查并解决输入电压发生变化但ADC读取数据无变化的问题。

[本文内容由国芯人工智能辅助生成,仅供参考]

ercircle 发表于 2025-6-16 16:47:56

GPIO高阻输入配置看着没有呢

ADC参考开天斧例程:08-16路ADC轮询-每路16次ADC转换取中间8次求平均值-串口1返回结果
https://www.stcaimcu.com/data/download/DemoCode/STC8H8K64U-45MHz-LQFP64-DIP64-DEMO-CODE.zip

migao 发表于 2025-6-16 17:46:54

ercircle 发表于 2025-6-16 16:47
GPIO高阻输入配置看着没有呢

ADC参考开天斧例程:08-16路ADC轮询-每路16次ADC转换取中间8次求平均值-串口1 ...
请问下,GPIO高阻输入配置看着没有呢----如何配置合适?硬件?软件?
我是P1.1 ADC输入,软件如下配置:

      P1M1 = 0x00;
      P1M0 = 0x00;
      
      P1M1 |= 0xf3;
          P1PU &= 0xf1;      //0:禁止端口内部的 4.1K上拉电阻

借鉴:

/*--------------------------------------
|------|------|-----------------------------------------------------|
| PnM1 | PnM0 |   I/O口工作模式                                     |
|------|------|-----------------------------------------------------|
|      |      |准双向口(传统8051端口模式,弱上拉)               |
|   0|   0|灌电流可达20mA,拉电流为270~150μA(存在制造误差)   |
|------|------|-----------------------------------------------------|
|   0|   1|推挽输出(强上拉输出,可达20mA,要加限流电阻)       |
|------|------|-----------------------------------------------------|
|   1|   0|高阻输入(电流既不能流入也不能流出)               |
|------|------|-----------------------------------------------------|
|      |      |开漏输出(Open-Drain),内部上拉电阻断开             |
|   1|   1|开漏模式既可读外部状态也可对外输出(高电平或低电   |
|      |      |平)。如要正确读外部状态或需要对外输出高电平,需外加 |
|      |      |上拉电阻,否则读不到外部状态,也对外输不出高电平。   |
|------|------|-----------------------------------------------------|
//------------------------------------*/

      

ercircle 发表于 2025-6-16 18:10:37

migao 发表于 2025-6-16 17:46
请问下,GPIO高阻输入配置看着没有呢----如何配置合适?硬件?软件?
我是P1.1 ADC输入,软件如下配置:




只配置要用的引脚即可,对比下上面发的例程,再检查下别的配置~

migao 发表于 2025-6-16 18:13:57

migao 发表于 2025-6-16 17:46
请问下,GPIO高阻输入配置看着没有呢----如何配置合适?硬件?软件?
我是P1.1 ADC输入,软件如下配置:



而且我发现一个奇怪现象,
DBG_PRINTF("BAT: %d\n",ADCValue);和
DBG_PRINTF("DAT: %d\n",ADCValue);
这两句屏蔽任何一个或两个,

DBG_PRINTF("LEDBatValue :%d \n",LEDBatValue);
LEDBatValue打印的数据LEDBatValue或BAT
DAT就为0,同时,没屏蔽的BAT或者DAT就有数据如果不屏蔽,打印的数据就出现.
请问是啥原因造成?如何解决?

ercircle 发表于 2025-6-16 21:07:28

migao 发表于 2025-6-16 18:13
而且我发现一个奇怪现象,
DBG_PRINTF("BAT: %d\n",ADCValue);和
DBG_PRINTF("DAT: %d\n",ADCValue);


格式与类型不符?ADCValue类型是int吗
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=6864&highlight=printf&page=1&extra=#pid60079

migao 发表于 2025-6-17 10:10:15

ercircle 发表于 2025-6-16 21:07
格式与类型不符?ADCValue类型是int吗
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=6864&hig ...

是下面这样定义的:
unsigned int ADCValue,ADCDatValue,ADCBatValue,DCDatValue,LEDBatValue,LEDBatValueTemp,LEDBatDisCharge;

ercircle 发表于 2025-6-17 10:26:41

migao 发表于 2025-6-17 10:10
是下面这样定义的:
unsigned int ADCValue,ADCDatValue,ADCBatValue,DCDatValue,LEDBatValue,LEDBa ...

看下上面帖子,也可以看看keil文档


migao 发表于 2025-6-17 13:49:56

ercircle 发表于 2025-6-17 10:26
看下上面帖子,也可以看看keil文档

按照上面来,没有解决问题.
页: [1] 2
查看完整版本: 用STC8H1K08测量电池电压,数据无变化. | 已搞定