找回密码
 立即注册
查看: 316|回复: 17

SOP16封装的STC8H8K64U单片机没有ADC功能?| 已解决

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 09:59:58 | 显示全部楼层 |阅读模式
我最近用了一块16脚的STC8H8K64U的单片机做项目,需要测出实际工作电压作条件启用某功能,但是我的代码实际测出内部通道15的ADC值一直是4095,反推出工作电压就是1.19V,这明显是不对的,同样的代码烧入16脚的STC8H2K12U的单片机中就能测出正常的工作电压是5V,所以我怀疑16脚的8H8K64U不支持ADC,但是我翻遍数据手册也没发现说不支持,请大神解惑!
e1.png

回复

使用道具 举报 送花

3

主题

1880

回帖

608

积分

等待验证会员

积分
608
发表于 2025-9-19 10:03:00 | 显示全部楼层
您好,感谢您的提问。

根据您所描述的情况,您使用的是SOP16封装的STC8H8K64U单片机,并尝试通过ADC功能读取内部通道15(通常为内部带隙基准电压通道)以推算实际供电电压。但您发现ADC值始终为4095(即12位ADC的最大值),换算后得出的电压值异常,而使用相同代码在STC8H2K12U上却能正常工作。

我们从以下几个方面来分析您的问题:

一、STC8H8K64U是否具备ADC功能?

根据宏晶科技(STC)官方发布的《STC8H系列技术手册》,STC8H8K64U 是具备12位逐次逼近型ADC模块的,且支持多达15个外部通道 + 1个内部通道(通道15)。

结论:STC8H8K64U确实具备ADC功能,且支持内部通道15。

二、为何ADC读数始终为4095?

ADC读数为最大值(4095),意味着输入电压等于或高于参考电压(Vref)。这可能由以下几种原因造成:

1. 供电电压异常
若实际供电电压高于参考电压(如Vref = 3.0V,而实际VCC > 3.0V),则ADC将饱和。
建议使用万用表测量实际VCC电压,确认其是否为标准5V或3.3V。

2. 参考电压配置错误
STC8H系列的ADC参考电压可通过寄存器选择为内部1.19V、2.56V、3.0V或外部Vref引脚。
若配置为内部1.19V参考电压,而实际VCC为5V,则通道15(内部基准电压)将无法正常反映VCC电压。
检查代码中是否正确配置了ADCREF寄存器,推荐使用内部2.56V或3.0V参考电压以提高测量精度。

3. 通道15采样时间不足或未启用
通道15为内部基准电压,其稳定时间较长(约100μs),若未等待其稳定就进行采样,可能导致读数异常。
建议在首次启动ADC或切换到通道15后,加入适当延时(例如Delayms(1))。

4. ADC模块未正确初始化
检查ADC使能位(ADCCONTR |= 0x80)、通道选择、转换启动方式等配置是否正确。
若ADC未正确启动或配置,可能返回默认最大值。

5. 芯片型号或封装限制
虽然STC8H8K64U在手册中说明支持ADC功能,但在某些封装中可能存在通道限制(如SOP16封装可能部分引脚复用受限)。
建议确认所使用封装是否为完整ADC通道支持版本,可参考数据手册中的“Pin Description”部分,确认是否有ADC引脚被复用为其他功能。

三、如何正确测量VCC电压?

STC8H系列单片机提供了通过内部通道15测量VCC的方法,公式如下:
  1. VCC = (InternalVoltage  4095) / ADCValue
复制代码

其中,InternalVoltage为内部基准电压,通常为1.19V、2.56V或3.0V(取决于配置)。

示例代码片段(建议参考):
  1. c
  2. void InitADC(void) {
  3.     ADCCONTR = 0x80;           // 开启ADC模块
  4.     P1ASF = 0x00;               // 设置P1口为通用IO(避免干扰)
  5.     Delayms(1);                // 等待稳定
  6. }
  7. unsigned int GetADCValue(unsigned char ch) {
  8.     ADCCONTR = (ADCCONTR & 0xE0) | ch | 0x10; // 选择通道并启动转换
  9.     while (!(ADCCONTR & 0x20));               // 等待转换完成
  10.     ADCCONTR &= ~0x20;                         // 清除标志
  11.     return ADCDATA;                            // 返回12位结果
  12. }
  13. float GetVcc(void) {
  14.     unsigned int adcval;
  15.     float internalref = 2.56; // 假设使用2.56V参考电压
  16.     InitADC();
  17.     adcval = GetADCValue(15); // 读取内部通道15
  18.     if (adcval == 0) adcval = 1;
  19.     return (internalref  4095) / adcval;
  20. }
复制代码

四、建议与排查步骤

1. 确认参考电压配置是否正确(1.19V、2.56V、3.0V)。
2. 检查通道15是否被正确选择并等待稳定时间。
3. 确认ADC模块已正确初始化和启动。
4. 使用万用表测量实际VCC电压,排除外部电源问题。
5. 查阅手册确认所用封装是否支持完整ADC功能。
6. 更换芯片测试,排除硬件损坏可能。

五、结语

综上所述,SOP16封装的STC8H8K64U是支持ADC功能的,包括内部通道15的电压测量。您遇到的问题更可能是由于参考电压配置不当、采样时间不足或初始化错误所致,而非芯片本身不支持ADC。

建议您按照上述思路逐一排查,相信可以找到问题所在。若您愿意提供具体代码或配置截图,也欢迎继续交流,我将尽力协助。

祝您项目顺利!

—— 国芯人工智能

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:560
  • 最近打卡:2025-10-16 05:35:53
已绑定手机

17

主题

768

回帖

2322

积分

金牌会员

积分
2322
发表于 2025-9-19 13:37:59 | 显示全部楼层
仔细看看数据手册,跟使用的哪一个ADC通道有关系
截图202509191337228716.jpg
截图202509191337562260.jpg
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 15:11:48 | 显示全部楼层
小*** 发表于 2025-9-19 13:37
仔细看看数据手册,跟使用的哪一个ADC通道有关系

我使用的是ADC通道15,这是内部参考电源通道,和管脚无关吧
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 15:24:54 | 显示全部楼层

#include "STC8H.H"
#include "stc32_stc8_usb.h"
#include "intrins.h"

#define MAIN_Fosc  12000000UL  //定义主时钟 24000000L

sbit LED       = P1^0;    //运行灯
u16        FlashDelay=0;//运行灯计闪烁驱动计数器

void delay_ms(u8 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 10000;
        while(--i);   //10T per loop
    }while(--ms);
}


unsigned int VDDA; // VDDA的电压值 单位毫伏
unsigned int BGV; // 内部参考电压值 单位毫伏

void ADCInit()
{
       
        BGV=((unsigned int)CHIPID7<<8)+(unsigned int)CHIPID8;
       
        ADCCFG = 0X2F; // 设置ADC时钟 = 24000000/2/16/512 = 1465Hz 转换结果右对齐
}

u16 ADCRead(int channel)
{
          ADC_RES = 0;
    ADC_RESL = 0;

    ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel;    //启动 AD 转换
    _nop_();
    _nop_();
    _nop_();
    _nop_();

    while((ADC_CONTR & 0x20) == 0)  ;   //wait for ADC finish
    ADC_CONTR &= ~0x20;     //清除ADC结束标志
    return  (((u16)ADC_RES << 8) | ADC_RESL);
}


void main()
{
   u8  i;
  u16 res;

    //系统初始化
          P_SW2 |= 0x80;     //扩展寄存器(XFR)访问使能
   
    P0M1 = 0x00;   P0M0 = 0x00;
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M1 = 0x00;   P3M0 = 0x00;
    P4M1 = 0x00;   P4M0 = 0x00;
    P5M1 = 0x00;   P5M0 = 0x00;
    P6M1 = 0x00;   P6M0 = 0x00;
    P7M1 = 0x00;   P7M0 = 0x00;
       
    usb_init();      //USB CDC 接口配置
    EA = 1;
       
   ADCInit();
       
    while (1)
    {

                                                delay_ms(1);
                       
                                          FlashDelay++;
                                               
                                                if (FlashDelay==2000) LED=0;//运行灯
                                                if (FlashDelay==2100) LED=1;
                                                       
                                                if (FlashDelay==2400) LED=0;//运行灯
                                                if (FlashDelay==2500)       
                                                {
                                                                 LED=1;
                                                                 FlashDelay=0;
                                                       
                        /************************ADC 15                ***********************************************/               
                                                       
                                                                        ADC_CONTR = 0x80; // 使能ADC模块 并选择第15通道                                                                       
                                                                        ADCRead(15);  
                                                                        ADCRead(15); //前两个数据建议丢弃
                                                                        res = 0;
                                                                        for (i=0; i<8; i++)
                                                                        {
                                                                                res += ADCRead(15); //读取 8 次数据
                                                                        }
                                                                        res >>= 3; //取平均值
                                                                       
                                                                //        vcc = (4096L * 1.19 / res); //(12 位 ADC 算法)计算 VREF 管脚电压,即电池电压
                                                                        VDDA =(unsigned int)((unsigned long)BGV*4096UL/(unsigned long)res);                                                                       
                                                       
                                                                        printf_usb("ADC15=%d   VCC=%dmV\r\n",res,VDDA);                                                                       
                                                                                                                                       

                                                }               
                       

                       
        if (bUsbOutReady)
        {
                                                                               
            USB_SendData(UsbOutBuffer,OutNumber);//);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
                                          usb_OUT_done();
                                       
        }
                               
    }
}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 15:37:40 | 显示全部楼层
调试CDC串口输出如下图:可以看到
[15:22:56.510]接收←ADC15=1052   VCC=4652mV    这个是同一代码我烧录到16脚的8H2K12U单片机中输出的电压信号完全正常

[15:23:37.137]接收←ADC15=4095   VCC=1189mV    这个是我上面代码烧录到16脚的8H8K64U单片机后输出的CDC串口数据,就不对了

以上都是针对测量ADC15通道数据来反推VCC 电源电压

test.png
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 15:38:31 | 显示全部楼层
百思不得其解
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:200
  • 最近打卡:2025-10-15 13:18:53

77

主题

6775

回帖

1万

积分

超级版主

积分
14384
发表于 2025-9-19 18:24:17 | 显示全部楼层
你ADC值为4095,怎么可能计算出来1.190V?你是怎么计算的?
你的AVREF接电压多少V?
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:524
  • 最近打卡:2025-10-16 10:25:30

9

主题

477

回帖

3329

积分

论坛元老

积分
3329
发表于 2025-9-19 21:06:41 | 显示全部楼层
建议先用官方例程去检查验证硬件有没有问题,例程运行没问题后,再检查自己的程序哪里不合适
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-20 03:15:11

1

主题

12

回帖

49

积分

新手上路

积分
49
发表于 2025-9-19 22:42:18 | 显示全部楼层
梁*** 发表于 2025-9-19 18:24
你ADC值为4095,在呢么可能计算出来1.190V?你是怎么计算的?
你的AVREF接电压多少V? ...

可以看我代码:公式 VDDA=  BGV*4096/adc
也就是:1.19*4096再除以ADC值4095=1.19V

点评

你测量下AVREF的电压是多少V,这个你没有提供。  详情 回复 发表于 2025-9-20 13:59
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-16 10:41 , Processed in 0.156675 second(s), 108 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表