8H4K32TL ADC读取失败问题请教
如图。ADC采样电路用一个10K电阻上拉到5V,一个负温度系数的热敏电阻。用万用表测量采样点电压会随着热敏电阻上温度不同测量到的电压不同。
看手册1344页P07不能配置为ADC,已经将P07跳线到P10.
程序用了Demo程序,在P4口接了8个LED指示灯,执行程序拾指示灯点亮一部分,不管我NTC温度怎么变化,指示灯都不变动。
请教问题需要怎么才能读取正确的ADC数据? 谢谢
代码如下:
void ADC_Isr() interrupt 5
{
ADC_CONTR&=~0x20;
P4=ADC_RES ;
ADC_CONTR|=~0x40;
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P1M0 = 0x00; //设置P1.0为ADC口
P1M1 = 0x10;
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC模块
EADC=1;
EA=1;
ADC_CONTR |= 0x40; //启动AD转换
while (1)
{
ADC_CONTR |= 0x40; //启动AD转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC完成标志
ADC_CONTR &= ~0x20; //清完成标志
P4 = ADC_RES; //读取ADC结果
}
}
根据您提供的信息,STC8H4K32TL ADC读取失败的问题可能涉及多个方面。以下是对问题的分析及建议:
1. ADC引脚配置问题
您提到已将P07跳线至P10,并在代码中设置了P1M0 = 0x00; P1M1 = 0x10;,此配置是正确的,用于将P1.4(即P10)设置为ADC输入引脚。但需确认是否使用了正确的ADC通道。例如,若ADC通道选择为CH4,则应确保P1.4作为ADC输入。
2. ADC初始化配置不完整
您的代码中未明确设置ADC控制寄存器(如ADCCONTR),导致ADC可能未正确启动。建议补充以下初始化步骤:
设置ADC使能位:ADCCONTR |= 0x80;
选择ADC通道:ADCCONTR &= ~0x0F; ADCCONTR |= 0x04;(假设选择CH4)
设置ADC采样时间:ADCTIM = 0x3f;(如您所设)
3. ADC中断与数据读取逻辑问题
您的中断服务程序中,ADCCONTR&=~0x20;用于清除ADC转换完成标志,但后续操作P4=ADCRES;可能存在问题。建议在中断中仅读取ADC结果,并通过主循环更新LED状态,避免直接在中断中操作输出端口。
4. ADC采样电路与信号完整性
虽然您已通过万用表验证采样点电压随温度变化,但需确保热敏电阻与上拉电阻的阻值匹配,且ADC输入范围(0-5V)与实际电压一致。若ADC参考电压(VREF)未正确配置,可能导致读数异常。
5. ADC时钟与采样率
确保系统时钟频率与ADC时序要求匹配。若系统时钟过快,可能影响ADC采样精度,建议查阅手册确认ADC最大采样率。
6. 代码逻辑与LED控制
您的主函数中未包含ADC启动逻辑(如ADCCONTR |= 0x40;),导致ADC可能未开始转换。此外,LED状态更新应基于ADC结果,而非固定值。建议在主循环中添加ADC启动和结果读取逻辑。
总结建议:
补充ADC初始化配置,确保通道、时序和使能位正确。
优化中断服务程序,仅读取ADC结果,避免直接操作输出。
在主循环中启动ADC并读取结果,更新LED状态。
验证ADC参考电压和采样电路设计,确保信号完整性。
以上调整后,ADC应能正确读取热敏电阻电压,并根据温度变化控制LED状态。如问题仍未解决,建议使用示波器或逻辑分析仪进一步排查信号路径和时序问题。
[本文内容由国芯人工智能辅助生成,仅供参考] #include "reg51.h"
#include "intrins.h"
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;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P1M0 = 0x00; //设置P1.0为ADC口
P1M1 = 0x01;
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC模块
while (1)
{
ADC_CONTR |= 0x40; //启动AD转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC完成标志
ADC_CONTR &= ~0x20; //清完成标志
P2 = ADC_RES; //读取ADC结果
}
}
测试Demo参考这个官方提供的调整出来的 P1M0 = 0x00; //设置P1.0为ADC口 前面这里注释错误,实际用的是P1.4
P1M1 = 0x01; //测试ADC 的完整代码如下
#include "STC8H.h"
#include <intrins.h>
#define MAIN_Fosc11059200L// 11059200L // 定义主时钟频率(11.0592MHz)24000000UL//主时钟频率
#define PWM_Freq1000 //PWM基础频率(Hz)
#define T1MS (65536 - MAIN_Fosc/1000)// 1ms定时计算
#define BRT (65536 - (MAIN_Fosc/115200+2)/4)// 加2操作是为了让Keil编译器自动实现四舍五入运算
int *BGV; //内部参考信号源值存放在idata中,idata的EFH地址存放高字节
//F0H地址存放低字节,电压单位为豪富mV
void ADCInit()
{
ADCTIM=0x3f;
ADCCFG=0x2f;
ADC_CONTR=0x8f;
}
int ADCRead()
{
int res;
ADC_CONTR|=~0x40;
//nop();
//nop();
while(!(ADC_CONTR&0x20));
ADC_CONTR&=~0x20;
res=(ADC_RES<<8)|ADC_RESL;
return res;
}
void ADC_Isr() interrupt 5
{
ADC_CONTR&=~0x20;
P4=ADC_RES ;
ADC_CONTR|=~0x40;
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P1M0 = 0x00; //设置P1.4为ADC口
P1M1 = 0x10;
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC模块
EADC=1;
EA=1;
ADC_CONTR |= 0x40; //启动AD转换
while (1)
{
ADC_CONTR |= 0x40; //启动AD转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC完成标志
ADC_CONTR &= ~0x20; //清完成标志
P4 = ADC_RES; //读取ADC结果
}
}
普信杨133 发表于 2025-8-29 16:20
//测试ADC 的完整代码如下
#include "STC8H.h"
#include
首先用例程代码能否采集变化电压,比如直接测VCC或GND?
然后示波器能否量到NTC电阻采集侧的电压变化?
https://www.stcaimcu.com/data/download/DemoCode/STC8H8K64U-DEMO-CODE-V9.6.zip
普信杨133 发表于 2025-8-29 16:20
//测试ADC 的完整代码如下
#include "STC8H.h"
#include
你这里只将P14设置为了高阻输入,但是与之并联的P07没有处理,这会导致P14被P07的默认高电平拉高,这样ADC就只能采样到最大值,且不会有变化。
将P07一并设置为高阻输入后,就可以读到ADC值了 王昱顺 发表于 2025-8-29 17:24
你这里只将P14设置为了高阻输入,但是与之并联的P07没有处理,这会导致P14被P07的默认高电平拉高,这样AD ...
是原来板上连到P0.7,后来看手册P0.7不能配置ADC,割开P0.7跳到P1.4去了 ercircle 发表于 2025-8-29 17:17
首先用例程代码能否采集变化电压,比如直接测VCC或GND?
然后示波器能否量到NTC电阻采集侧的电压变化?
用官方Demo做的,P4口上LED显示的没有变化。
用万用表测量上拉电阻和NTC之间的电压是随着NTC温度升高电压变化了的。 普信杨133 发表于 2025-8-30 17:30
用官方Demo做的,P4口上LED显示的没有变化。
用万用表测量上拉电阻和NTC之间的电压是随着NTC温度升高电压 ...
删掉这一行,否则关闭XFR标志位后,就无法访问地址在xdata区域的特殊功能寄存器了
这会导致后面的操作失效
页:
[1]
2