ADC转换不正常
以下是我的程序,使用的是20脚的STC8H1K17T奇怪的是 以前能用的ADC程序直接用也用不了了
电位器稍微拧动一点就到了对应的判断值
是配置的问题吗?
// 头文件
#include "STC8H.H" // 引入STC8系列单片机的头文件
#include "intrins.h" // 引入Keil的内部函数头文件
// 端口定义
sbit GM = P3^3; // 定义AD光敏输入端口
sbit LED = P5^4; // LED
// 宏定义
// 数据存储
#define ADC_CHANNEL_GM 11 // 光敏 ADC 通道
#define HIGH_THRESHOLD 4000 // 亮度变暗的上阈值
#define LOW_THRESHOLD3500 // 亮度变亮的下阈值
// 数据类型
#defineuint32 unsigned long // 定义32位无符号整数类型
#defineuint16 unsigned int // 定义16位无符号整数类型
#defineuint8 unsigned char // 定义8位无符号整数类型
// 1ms延时函数
void delay_ms(uint16 x)
{
uint16 j, i;
for(j = 0; j < x; j++)
{
for(i = 0; i < 1580; i++); // 延时代码
}
}
// ADC初始化
void ADC_INIT()
{
ADC_CONTR |= 0x80; // 打开ADC电源
ADCCFG &= ~0x0f; // 清除速度选择位
ADCCFG |= 0x02; // 设置采样速率为 SPEED=2,即 50KSPS
ADCTIM = 0x35; // CSSETUP(0), CSHOLD(1), SMPDUTY(21)
ADC_CONTR &= 0xDF; // 清AD转换完成标志
EADC = 0; // 禁止ADC中断
ADCCFG |= 0x20; // ADC转换结果12位数
}
// ADC口检测AD转换值函数
uint16 ADC_ReadChannel(uint8 channel)
{
uint16 result;
ADC_CONTR &= 0xF0; // 清通道选择位
ADC_CONTR |= (channel & 0x0F); // 设置通道
ADC_CONTR &= ~0x20; // 清完成标志
ADC_CONTR |= 0x40; // 启动转换
while (!(ADC_CONTR & 0x20)); // 等待完成
ADC_CONTR &= ~0x20; // 清完成标志
result = ADC_RES; // 首先读取高八位的数值
result <<= 8;
result|= ADC_RESL; // 读取低4位
return result;
}
// ADC值处理
void process_gm(uint8 channel)
{
uint16 temp = ADC_ReadChannel(channel);// 用传入的通道号
uint16 voltage = (uint32)temp * 5000 / 4095;
if (voltage > HIGH_THRESHOLD)
{
LED = 1;
}
else if (voltage < LOW_THRESHOLD)
{
LED = 0;
}
}
// 系统初始化
void system_init()
{
delay_ms(1000); // 延时1s 待市电稳定
// 引脚定义
P5M0 |= 0x10; P5M1 &= ~0x10; // P54 强推挽
LED = 0; // 关灯
ADC_INIT(); // ADC初始化
}
// 主函数
void main()
{
system_init();
while (1)
{
process_gm(ADC_CHANNEL_GM);// AD通道
}
}
根据您提供的信息,结合STC8H1K17T单片机的ADC特性及常见配置问题,以下是针对“ADC转换不正常”问题的专业分析与建议:
一、问题现象分析
您描述的现象为:“电位器稍微拧动一点就到了对应的判断值”,表明ADC读数变化较大,可能表现为以下几种情况:
1. ADC采样不稳定或精度不足:ADC数值波动大,导致判断条件容易触发。
2. ADC通道配置错误:未正确配置ADC通道或参考电压源。
3. 外部电路干扰或连接问题:如电位器接线松动、电源噪声等。
4. ADC初始化设置不当:例如采样时间、分辨率、使能位等配置不正确。
二、代码与配置检查建议
您提供的代码片段中缺少关键的ADC初始化部分,建议补充以下内容:
1. ADC初始化配置(示例)
c
// ADC配置函数
void ADCInit(void)
{
// 使能ADC时钟
PCON |= 0x01; // 设置ADC时钟源(具体需参考数据手册)
// 配置ADC通道
ADCCON = 0x00; // 清除配置寄存器
ADCCON |= (ADCCHANNELGM注意:ADCCHANNELGM的值需要根据STC8H1K17T的数据手册确认。例如,某些型号的ADC通道号范围为0~7,而有些支持更高位数。若配置错误,可能导致ADC无法正确采集信号。
2. ADC读取函数c
uint16 ADCRead(void)
{
uint16 adcvalue = 0;
// 启动ADC转换
ADCCON |= 0x80; // 触发一次转换
// 等待转换完成
while(!(ADCCON & 0x40));// 检查转换是否完成
// 读取ADC结果
adcvalue = ADCDATAH建议在每次读取前确保ADC已正确启动并完成转换。
三、常见配置问题排查
| 问题点 | 可能原因 | 解决方案 |
|--------|----------|-----------|
| ADC通道未正确选择 | 通道号配置错误 | 根据数据手册确认ADC通道号 |
| ADC参考电压设置错误 | 未使用内部参考电压或外部参考电压不稳定 | 检查VDD和VREF引脚连接,确保稳定 |
| ADC采样时间不足 | 转换速度过快导致采样不准确 | 增加采样时间(通过ADCCON寄存器调整) |
| 外部干扰 | 电位器信号受干扰 | 使用屏蔽线,增加滤波电容 |
| ADC未使能 | 初始化代码未启用ADC模块 | 确保ADCCON寄存器中使能位被置1 |
四、其他建议
检查电源稳定性:ADC对电源噪声敏感,建议使用稳压模块供电,并在电源端添加去耦电容(如10μF电解电容 + 0.1μF陶瓷电容)。
测试ADC功能:可尝试将ADC输入接到固定电压(如GND或VCC),观察输出是否稳定,以排除硬件问题。
更新固件版本:若您使用的是较旧版本的库文件,可能存在兼容性问题,建议升级至最新版本。
五、结论
ADC转换异常可能是由多种因素引起的,包括但不限于配置错误、外部干扰或硬件问题。建议从以下几个方面进行排查:
1. 检查ADC通道配置是否正确;
2. 确保ADC初始化流程完整;
3. 检查外部电路稳定性;
4. 测试ADC基本功能以定位问题。
如需进一步协助,请提供完整的程序代码及ADC相关寄存器配置信息,以便更精确地分析问题根源。
如需帮助调试或优化ADC性能,欢迎继续提问。
[本文内容由国芯人工智能辅助生成,仅供参考] 这个也没开EAXFR
先用例程试下:
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=19767&pid=182980
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=19767&pid=183018
/***************************************************************
* 文件名: main.c
* 芯片型号: STC8H 系列
* 功能: 通过 ADC 检测电网电压,控制 LED 灯状态
* 开发环境: Keil C51
***************************************************************/
/*------------------ 头文件 ------------------*/
#include "STC8H.H" // STC8 系列单片机头文件
#include "intrins.h" // Keil 内部函数头文件
/*------------------ 宏定义 ------------------*/
// 电压阈值 (单位: mV)
#define HIGH_HP 3500 // 电压上阈值,1000 mV = 1.0V
#define ADC_CHANNEL_HP 3 // 电网电压 ADC 通道
// 数据类型定义
#define uint32unsigned long // 32位无符号整数
#define uint16unsigned int // 16位无符号整数
#define uint8 unsigned char // 8位无符号整数
/*------------------ 端口定义 ------------------*/
sbit LED = P5^4; // LED 指示灯
/*------------------ 函数定义 ------------------*/
/**
* @brief 延时函数,粗略延时 x 毫秒
* @param x延时时间 (ms)
* @note 实际延时受主频影响,不够精确
*/
void delay_ms(uint16 x)
{
uint16 j, i;
for (j = 0; j < x; j++)
{
for (i = 0; i < 1580; i++); // 循环延时
}
}
/**
* @brief ADC 初始化
* @note 设置为 12 位精度,采样速率 50KSPS
*/
void ADC_INIT()
{
ADC_CONTR |= 0x80; // 打开 ADC 电源
ADCCFG &= ~0x0f; // 清除速度选择位
ADCCFG |= 0x02; // 设置采样速率 SPEED=2 (50KSPS)
ADCTIM = 0x35; // CSSETUP(0), CSHOLD(1), SMPDUTY(21)
ADC_CONTR &= 0xDF; // 清转换完成标志
EADC = 0; // 禁止 ADC 中断
ADCCFG |= 0x20; // 12 位 ADC 模式
}
/**
* @brief 读取指定 ADC 通道的数值
* @param channel 通道号 (0~15)
* @return 转换结果,范围 0~4095 (12位)
*/
uint16 ADC_ReadChannel(uint8 channel)
{
uint16 result;
ADC_CONTR &= 0xF0; // 清除通道选择位
ADC_CONTR |= (channel & 0x0F);// 设置 ADC 通道
ADC_CONTR &= ~0x20; // 清完成标志
ADC_CONTR |= 0x40; // 启动转换
while (!(ADC_CONTR & 0x20)); // 等待转换完成
ADC_CONTR &= ~0x20; // 清完成标志
result = ADC_RES; // 高 8 位
result <<= 8;
result |= ADC_RESL; // 低 4 位
return result;
}
/**
* @brief 电网电压处理函数
* @param channel 电网 ADC 通道号
* @note 电压换算公式: voltage = ADC * 5000 / 4095 (mV)
*/
void process_hp(uint8 channel)
{
uint16 temp = ADC_ReadChannel(channel); // 读取 ADC
uint16 voltage = (uint32)temp * 5000 / 4095; // 转换为 mV
if (voltage > HIGH_HP) // 电压超过 1.0V
{
LED = 1; // 开灯
}
else
{
LED = 0; // 关灯
}
}
/**
* @brief 系统初始化
* @note 初始化 IO 口、LED、ADC
*/
void system_init()
{
P_SW2 |= 0x80; // 使能访问 XFR
delay_ms(1000); // 上电延时 1s,等待市电稳定
// IO 模式配置
P5M0 |= 0x10;
P5M1 &= ~0x10; // P5.4 推挽输出 (LED)
LED = 0; // 初始化 LED 关闭
ADC_INIT(); // 初始化 ADC
}
/**
* @brief 主函数
*/
void main()
{
system_init();// 系统初始化
while (1)
{
process_hp(ADC_CHANNEL_HP); // 检测电网电压通道
}
}
这是我简化了的程序 并打开的XFR
问题还是稍微拧动电位器就会触发阈值 而不是到3500 电位器硬件是验证过的 在别的芯片上是可以正常使用的
使用例程去修改成这样也是稍微扭动电位器会直接超过阈值 贴下电路看看 如图 不是在PCB上部署的 只是用跳线在测试
芯片烧录座接在link 电位器接在5V和GND 输出接在芯片IO HyunYong_7782 发表于 2025-8-27 01:33
如图 不是在PCB上部署的 只是用跳线在测试
芯片烧录座接在link 电位器接在5V和GND 输出接在芯片IO ...
破案了 又去对了一次规格书
在用外部参考源的时候VCC没有能力直接拾取参考电压
需要把VCC和 ADC_VREF+接在一起
稍微拧动就点亮是因为浮空了ADC_VREF+引脚 那么参考源就很低 所以稍微拧动就能亮
RT
页:
[1]