AD1直接接到VCC引脚的,有10UF和0.1UF电容,并用示波器监测,绝对不会有瞬间到0的干扰,而且现板上没有任何别的电路,只有最小元件MCU,也没有其它外围电路影响。附件是串口回传的数据
STC8H1K08 ADC 第15通道(内部1.19V)-AD1通道 ,交替打印15通道AD1通道原始10位值结果.txt
(25.83 KB, 下载次数: 52)
/****************************************************
功能:STC8H1K08 ADC 第15通道(内部1.19V)测试/AD1通道 ,交替打印15通道/AD1通道原始10位值
----------------------------------------------------------------------------
【硬件配置】与之前相同
1. 芯片: STC8H1K08-36I-TSSOP20
2. 第15通道为芯片内部固定1.19V参考源,
3. AD1为(P1.1)第20脚,配置为高阻输入
3. 串口1(P3.0/P3.1) 打印输出: 115200,8,N,1
----------------------------------------------------------------------------
【目的】验证ADC模块本身是否稳定
测第15通道读数稳定(约 1024*1.19/VRef), 不出现0
AD1(P1.1,外接稳压供电的VCC引脚)读数大部分为 1023(满量程),但偶发出现 0000,
说明ADC模块和读时序没问题, 问题暂找不到原因
【软件功能】
1. 时钟: 内部 11.0592MHz (ISP下载软件设置, 代码中无需配置)
2. 定时器0做0.5ms节拍
3. 主循环中读第15通道, 打印,读第1通道, 识别码A1/B2交替
【读法】ADCCFG=0x0f 左对齐: 10位结果 = (ADC_RES<<2)|(ADC_RESL>>6)
----------------------------------------------------------------------------
******************************************************/
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
#define P1IE (*(unsigned char volatile xdata *)0xfe31)
sfr AUXR = 0x8e;
sfr ADC_CONTR = 0xbc;
sfr ADC_RES = 0xbd;
sfr ADC_RESL = 0xbe;
sfr ADCCFG = 0xde;
sfr P_SW2 = 0xba;
#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
/* 全局变量区 */
bit busy;
bit flag; //T0中断标志
bit tx_toggle; //识别码翻转标志: 0发0xA1, 1发0xB2
char buf[8];
unsigned int adcval; //ADC原始10位结果
void UartIsr() interrupt 4
{
if (TI)
{
TI = 0;
busy = 0;
}
if (RI)
{
RI = 0;
}
}
void UartInit()
{
SCON = 0x50;
TMOD = 0x00;
TL1 = BRT;
TH1 = BRT >> 8;
TR1 = 1;
AUXR = 0x40;
busy = 0;
}
void UartSend(char dat)
{
while (busy);
busy = 1;
SBUF = dat;
}
void UartSendStr(char *str)
{
while (*str != '\0')
{
UartSend(*str);
str++;
}
}
void ADCInit()
{
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16, 左对齐
}
/* 读第15通道(内部1.19V)一次, 返回10位结果 */
/* 读指定通道一次, 返回10位结果 */
int ADCRead(unsigned char ch)
{
unsigned int res;
unsigned char hi, lo;
ADC_CONTR = 0x80 | ch; //使能ADC, 选通道ch (ch=0x01为AD1, ch=0x0F为第15通道)
ADC_CONTR |= 0x40; //启动转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询完成标志
ADC_CONTR &= ~0x20; //清完成标志
hi = ADC_RES; //先锁存高8位
lo = ADC_RESL; //再锁存低位
res = ((unsigned int)hi << 2) | ((unsigned int)lo >> 6); //左对齐10位
return res;
}
void Timer0_Init(void) //0.5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xEA; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1; //使能总中断
}
void main()
{
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00; //第15通道是内部通道, 不需要配置P1口
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P_SW2 |= 0x80; //使能访问XFR
P1IE &= ~0x02; //关闭P1.1数字输入(作为ADC口必须关)
P_SW2 &= 0x7f; //不访问XFR了, 可关
tx_toggle = 0;
ADCInit();
UartInit();
Timer0_Init();
ES = 1;
while (flag); flag = 0; //等0.5ms
while (flag); flag = 0; //再等0.5ms
while (1)
{
if (flag)
{
flag = 0;
if (tx_toggle == 0) // 交替读两个通道
adcval = ADCRead(0x01); // AD1 (P1.1)
else
adcval = ADCRead(0x0F); // 第15通道(内部1.19V)
buf[0] = (adcval / 1000) + '0';
buf[1] = (adcval / 100) % 10 + '0';
buf[2] = (adcval / 10) % 10 + '0';
buf[3] = adcval % 10 + '0';
buf[4] = tx_toggle ? 0xB2 : 0xA1; // A1=AD1, B2=第15通道
buf[5] = '\r';
buf[6] = '\n';
buf[7] = '\0';
tx_toggle = !tx_toggle;
UartSendStr(buf);
}
}
}
//T0 中断-节拍器
void Timer0_Isr(void) interrupt 1
{
flag = 1;
}
复制代码 与AI互动的记录:
STC8H1K08 ADC 偶发读 0 问题 实验记录
芯片型号:STC8H1K08-36I-TSSOP20
时钟:内部 11.0592MHz(ISP 下载软件设置)
串口:串口1(P3.0/P3.1),115200, 8, N, 1
测试通道:AD1(P1.1 外部引脚,接 VCC,10μF+0.1μF 滤波);对比通道:ADC 第15通道(内部固定 1.19V)
VRef+(第9脚):接 VCC(5V)
日期:本次实验记录
一、问题现象
AD1(P1.1,接稳压 VCC)读数大部分为 1023(满量程),但偶发出现 0000,也出现过 0511 / 0032 / 0010 等小值。
现象可稳定复现,且随代码版本变化(从偶发到连续)。
识别码约定:A1 = AD1(P1.1),B2 = 第15通道(内部1.19V)。
二、关键实验与结果
实验1:原始代码(只读 AD1,P1.1 接 VCC)
结果:稳定 1023,偶发 0000 / 0511 / 0032 / 0010。
实验2:加 ADC_CONTR &= ~0x20;(启动前清 ADC_FLAG)
结果:仍偶发 0000 → ADC_FLAG 残留不是成因。
实验3:读结果移到清标志之前 + 加超时保护
结果:仍偶发 0000 → 读值时序不是成因。
实验4:只读第15通道(内部1.19V,ADC_CHS=1111)
结果:
读数稳定 240(理论值 ≈ 1024×1.19/5 ≈ 244,实测 240 合理,含内部1.19V ±1% 误差);
偶尔跳 241/242;
全程从未出现 0000。
实验5:交替读 AD1(A1)与第15通道(B2)
结果:
B2(第15通道)全程稳定 240~243,从未出 0;
A1(AD1)仍偶发 0000;
A1 掉 0 的那一帧,紧邻的 B2 完全正常。
三、已确认的结论(由实验4、5 证明)
ADC 模块本身正常(第15通道稳定);
读值代码、串口打印、时序、通道切换全部正常(第15通道用同一套代码,稳定);
电源干扰被排除(第15通道测的就是 VCC 相关,它不跳);
满量程边界误差被排除(第15通道在 240,非边界,也正常);
问题 100% 锁定在"AD1(P1.1)这个外部引脚通道"本身。
四、已排除的假设(均经实测或推理否定)
序号 假设 排除依据
1 ADC 电源未等 1ms 电源自始至终未关,中段才出错
2 同通道需丢首次 通道固定,且第15通道不丢也正常
3 ADC_FLAG 残留 加清标志后仍出 0(实验2)
4 C51 类型截断 第15通道用同一读法,正常(实验4)
5 采样电容充不到位 撤回;P1.1 为稳压直供
6 满量程边界 + 误差 0 是数量级错误,误差解释不了
7 电源干扰 第15通道不跳(实验4/5)
8 通道切换后首次脏 交替读时 B2 仍正常(实验5)
注:"P1IE 关闭数字输入" 与 "P1.1 输出锁存器被清0" 两项尚未最终确认,见第六节。
五、当前最可疑的原因(待验证)
P1.1 输出锁存器(P1 端口 B1)可能被清 0:
若 P1 的 B1 = 0,则 P1.1 的内部输出驱动会试图把引脚拉低,与外部 VCC 顶牛;
采样瞬间被内部下拉拉向 0 → 读到 0;
第15通道是内部通道,没有输出锁存器,所以不受影响。
实验6:确认是否已加 P1IE(已加)
实验5 的数据是否在加了以下两行之后测的?(已加)
#define P1IE (*(unsigned char volatile xdata *)0xfe31) // 文件开头声明
...
P_SW2 |= 0x80; // 使能访问XFR
P1IE &= ~0x02; // 关闭P1.1数字输入
P_SW2 &= 0x7f;
📋
若已加仍出0 → P1IE 假设排除;已加
实验7:检查代码是否写过 P1 / P1.1
搜索代码里有没有 P1 = / P1 &= / P1 |= 之类;
若有,先删除,让 P1.1 锁存器保持复位默认值 1。
实验8:明确把 P1.1 锁存器置 1
在 main() 中 P1M1=0x02 之后加:
P1M0 = 0x00;
P1M1 = 0x02; //P1.1高阻输入(ADC口)
P1 |= 0x02; //★明确把P1.1锁存器置1, 防止内部下拉
📋
若加后 0000 消失 → 根因确认:P1.1 输出锁存器被清0,内部下拉顶牛外部VCC。
七、当前可用的测试代码骨架(交替读 AD1 / 第15通道)
/* ADCRead 必须带通道参数 */
int ADCRead(unsigned char ch)
{
unsigned int res;
unsigned char hi, lo;
ADC_CONTR = 0x80 | ch; //ch=0x01为AD1(P1.1), ch=0x0F为第15通道
ADC_CONTR |= 0x40; //启动转换
_nop_(); _nop_();
while (!(ADC_CONTR & 0x20)); //查询完成标志
ADC_CONTR &= ~0x20; //清完成标志
hi = ADC_RES; //先锁存
lo = ADC_RESL;
res = ((unsigned int)hi << 2) | ((unsigned int)lo >> 6); //左对齐10位
return res;
}
📋
主循环:
if (tx_toggle == 0) adcval = ADCRead(0x01); // AD1 (P1.1) → 识别码A1
else adcval = ADCRead(0x0F); // 第15通道 → 识别码B2
📋
八、关键参数备忘(避免明天重算)
项 值 说明
ADCTIM 0x3F CSSETUP=0, CSHOLD=1, SMPDUTY=31(手册推荐值)
ADCCFG 0x0F SPEED=1111(SYSclk/2/16), RESFMT=0 左对齐
10位结果读法 (ADC_RES<<2) | (ADC_RESL>>6) 左对齐
第15通道 ADC_CHS=1111, ADC_CONTR=0x8F 内部1.19V
第15通道理论值 ≈244 1024×1.19/5
P1M1 0x02 P1.1 高阻输入
P1IE 地址 FE31H, B1=P11IE XFR区,需 P_SW2|=0x80
识别码 A1=AD1, B2=第15通道
九、文档信息出处
手册《STC8H系列单片机》第「ADC模数转换,内部1.19V参考信号源」章节:ADC_CONTR/ADCCFG/ADCTIM 位定义、速度公式、第15通道、ADC_POWER 注意事项。
手册《STC8H系列单片机》第「I/O口」章节:PxM0/PxM1 模式表、PxIE(P1IE 地址 FE31H,B1=P11IE,复位值 1111,1111)。
手册《STC8H系列单片机》第「存储器」章节:EAXFR 使用说明(P_SW2 |= 0x80;)。
论坛《复现到了ADC出现0值的问题》等帖:官方"读到0=采样到0电压"的结论(供参考)。