SOP16封装的STC8H8K64U单片机没有ADC功能?| 已解决
我最近用了一块16脚的STC8H8K64U的单片机做项目,需要测出实际工作电压作条件启用某功能,但是我的代码实际测出内部通道15的ADC值一直是4095,反推出工作电压就是1.19V,这明显是不对的,同样的代码烧入16脚的STC8H2K12U的单片机中就能测出正常的工作电压是5V,所以我怀疑16脚的8H8K64U不支持ADC,但是我翻遍数据手册也没发现说不支持,请大神解惑!您好,感谢您的提问。
根据您所描述的情况,您使用的是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的方法,公式如下:
VCC = (InternalVoltage4095) / ADCValue
其中,InternalVoltage为内部基准电压,通常为1.19V、2.56V或3.0V(取决于配置)。
示例代码片段(建议参考):
c
void InitADC(void) {
ADCCONTR = 0x80; // 开启ADC模块
P1ASF = 0x00; // 设置P1口为通用IO(避免干扰)
Delayms(1); // 等待稳定
}
unsigned int GetADCValue(unsigned char ch) {
ADCCONTR = (ADCCONTR & 0xE0) | ch | 0x10; // 选择通道并启动转换
while (!(ADCCONTR & 0x20)); // 等待转换完成
ADCCONTR &= ~0x20; // 清除标志
return ADCDATA; // 返回12位结果
}
float GetVcc(void) {
unsigned int adcval;
float internalref = 2.56; // 假设使用2.56V参考电压
InitADC();
adcval = GetADCValue(15); // 读取内部通道15
if (adcval == 0) adcval = 1;
return (internalref4095) / adcval;
}
四、建议与排查步骤
1. 确认参考电压配置是否正确(1.19V、2.56V、3.0V)。
2. 检查通道15是否被正确选择并等待稳定时间。
3. 确认ADC模块已正确初始化和启动。
4. 使用万用表测量实际VCC电压,排除外部电源问题。
5. 查阅手册确认所用封装是否支持完整ADC功能。
6. 更换芯片测试,排除硬件损坏可能。
五、结语
综上所述,SOP16封装的STC8H8K64U是支持ADC功能的,包括内部通道15的电压测量。您遇到的问题更可能是由于参考电压配置不当、采样时间不足或初始化错误所致,而非芯片本身不支持ADC。
建议您按照上述思路逐一排查,相信可以找到问题所在。若您愿意提供具体代码或配置截图,也欢迎继续交流,我将尽力协助。
祝您项目顺利!
—— 国芯人工智能
[本文内容由国芯人工智能辅助生成,仅供参考] 仔细看看数据手册,跟使用的哪一个ADC通道有关系 小飞侠 发表于 2025-9-19 13:37
仔细看看数据手册,跟使用的哪一个ADC通道有关系
我使用的是ADC通道15,这是内部参考电源通道,和管脚无关吧
#include "STC8H.H"
#include "stc32_stc8_usb.h"
#include "intrins.h"
#define MAIN_Fosc12000000UL//定义主时钟 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()
{
u8i;
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();
}
}
}
调试CDC串口输出如下图:可以看到
接收←ADC15=1052 VCC=4652mV 这个是同一代码我烧录到16脚的8H2K12U单片机中输出的电压信号完全正常
接收←ADC15=4095 VCC=1189mV 这个是我上面代码烧录到16脚的8H8K64U单片机后输出的CDC串口数据,就不对了
以上都是针对测量ADC15通道数据来反推VCC 电源电压
百思不得其解{:4_167:} 你ADC值为4095,怎么可能计算出来1.190V?你是怎么计算的?
你的AVREF接电压多少V? 建议先用官方例程去检查验证硬件有没有问题,例程运行没问题后,再检查自己的程序哪里不合适 梁工 发表于 2025-9-19 18:24
你ADC值为4095,在呢么可能计算出来1.190V?你是怎么计算的?
你的AVREF接电压多少V? ...
可以看我代码:公式 VDDA=BGV*4096/adc
也就是:1.19*4096再除以ADC值4095=1.19V
页:
[1]
2