请教,关于ADC专换值偶尔为0的情况
单片机型号STC8G2k60s4P0.0为检测口,参考电压接到VCC,2576供电,
检测电压2V左右示波器检测无跳变,偶尔出现检测值为0的情况,求解
代码如下:
#include "STC8GXX.H"
#include "intrins.h"
unsigned char Value;
unsigned int UartOffTime;
void ADC_Init()
{
P0M0 = 0x00;
P0M1 = 0x01;
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置 ADC 内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置 ADC 时钟为系统时钟/2/16/16
ADC_CONTR = 0x88; //使能 ADC 模块
}
void UART_Init()//115200@22.1184
{
SCON = 0x50;
T2L = 0xD0;
T2H = 0xff;
AUXR = 0x15;
EA = 1;
ES = 1;
}
void Uart_Send_Byte(const unsigned char tdata)//
{
ES = 0;
TI = 0;
SBUF = tdata;
UartOffTime = 0;
while (!TI)
{
UartOffTime ++;
if(UartOffTime > 2000)
break;
}
TI = 0;
ES = 1;
return;
}
void Delay1ms(unsigned int k)//@22.1184MHz
{
unsigned char i;
unsigned char j;
for(; k>0; k--)
{
i = 29;
j = 183;
do
{
while (--j);
} while (--i);
}
}
void main()
{
ADC_Init();
UART_Init();
while(1)
{
ADC_CONTR = 0xc8; //启动 AD 转换
while (!(ADC_CONTR & 0x20)); //查询 ADC 完成标志
Value = ADC_RES; //读取 ADC 结果
ADC_CONTR &= ~0x20; //清完成标志
Uart_Send_Byte(Value);
Delay1ms(100);
if(Value == 0)
{ while(1); }
}
} 自己先顶一下 感觉AD转换都要软件滤波才行 XTXB 发表于 2020-8-24 12:51
感觉AD转换都要软件滤波才行
是的,如果搞不定只有滤波了 真有这种情况,根本就不是靠滤波来搞定的。 用示波器看一下时序对不对,是不是SPI读取的速度太快了,曾遇到过读取的速度太快了或者采样太快会偶尔读到很大值的问题。 HZKJ 发表于 2020-8-24 14:27
真有这种情况,根本就不是靠滤波来搞定的。
是啊,我也这么觉得 hanbing333444 发表于 2020-8-24 17:01
用示波器看一下时序对不对,是不是SPI读取的速度太快了,曾遇到过读取的速度太快了或者采样太快会偶尔读到 ...
示波器要如何看时序呢, LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者输入信号的波动情况。 一般是芯片问题的可能性极小。 HZKJ 发表于 2020-8-24 21:22
LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者 ...
是的,我估计也是电路问题 HZKJ 发表于 2020-8-24 21:22
LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者 ...
哈哈,是我没注意审题,还以为用的SPI读取的数据。 可以向STC技术支持要测试程序。 这几天我也遇到这样的问题, 用的芯片是 STC8H1K16 系列,用P1.0做为AD输入,刚上电前几秒容易出现采样为0的情况,后面也会出现,但很少。 小李非刀 发表于 2020-8-27 11:28
可以向STC技术支持要测试程序。
就是用测试程序测得,已经常用多次取平均的办法 52HLX 发表于 2020-9-10 22:00
这几天我也遇到这样的问题, 用的芯片是 STC8H1K16 系列,用P1.0做为AD输入,刚上电前几秒容易出现采样为0 ...
看来不止我遇到
还好是出现零 直接忽略 同样遇到会有小概率出现0 还有一种算法,就是在求平均值的基础上,先通过冒泡排序等方法,查找最大值和最小值,并且将这些最值去掉,然后才计算平均值,以消除极差对整体的影响。 kundi 发表于 2021-4-25 22:57
还有一种算法,就是在求平均值的基础上,先通过冒泡排序等方法,查找最大值和最小值,并且将这些最值去掉, ...
滤波是针对信号波动的应对措施,楼主这偶尔出现0值,已经是功能问题了,首先要解决功能问题。
猜测大概率还是程序问题,极小概率是单片机的bug等。 问了 R&D, 答复:1,给 MCU 的 内部ADC 模块电源打开后,等个 1ms, 等MCU内部的 ADC 电源稳定后再让 ADC工作; 2,适当加长对外部信号的采样时间,就是对ADC内部采样保持电容的充电或放电时间,时间够,内部才能和外部电势相等。新手这样那样的问题正常
这是个真正达到 10-BIT 精度的 内置 10-BIT ADC 使用ELL库试一下https://gitee.com/zeweni/ELL-8051-LIB
有STC8G的ADC测试例程https://gitee.com/zeweni/ELL-8051-LIB/tree/master/examples/STC8Gx/demo_adc
支持查询法和中断法
API手册中心:https://zewen-i.github.io/8051-ELL-API/_s_t_c8x___a_d_c_8h.html 泽文i 发表于 2021-4-30 19:03
使用ELL库试一下https://gitee.com/zeweni/ELL-8051-LIB
有STC8G的ADC测试例程https://gitee.com/zeweni/EL ...
感谢,我先试下 我遇到过偶尔检测4096的现象 shange144k8 发表于 2021-5-3 23:39
感谢,我先试下
问题解决了吗 我也遇到这个问题了,STC8G2K64S4,官方的测试程序,打印出来ADC的值,偶尔会为0。折腾了好久没搞定 估计是程序的健壮性问题。翻了下我多年前写的代码,ADC转换多了几个步骤,抛砖引玉:
偶尔读到0或满量程,硬件问题基本都是因为干扰,包括电源有干扰、输入信号有干扰、电路间有干扰,软件问题就更难判断了。
STC的ADC是开关电容的逼近式ADC,输入有一个采样电容,每次触发ADC都由硬件执行相同的时序,先采样,再做ADC,本身不会出现采样到电压却转换成0的情况。
大家可以测试STC官方的示波器程序,500KHz采样,你可以连续观察正弦波一小时,看看是否有突然变0的,波形是很容易看出来的,反正我没遇到过。
感觉STC推出的好多例子拉低了其应用难度,比如四轴飞控、无刷电机控制、简易示波器、USB通信。。。等等,太多了。 芯片 STC8G1K08A-8Pin
很简单的程序,也是因为读ADC返回值为0困扰了两天,读15通道的内部1.19V电压值正常。还在抓狂中...
while(1)
{
WDT_CONTR |= 0x10; //喂狗
Delay_ms(2); //延时
ADC_1V19 = GetADCResult(15); //采样内部1.19V基准电压
ADC_Pin8 = GetADCResult(3); //再采样8脚(ADC3)电压
Volt_Pin8 = 1.19 * ADC_Pin8 / ADC_1V19; //计算8脚(ADC3)电压
if(Volt_Pin8<3.6)
{
ShutDown = !ShutDown;
printf("ADC119=%u ADC3=%u Volt=%.2f\r\n",ADC_1V19,ADC_Pin8,Volt_Pin8);
}
}
unsigned int GetADCResult(char ch)
{
unsigned int ADCValue;
ADC_CONTR = 0xC0 | ch ; //开ADC转换
_nop_(); //等待2个NOP
_nop_();
while (!(ADC_CONTR & 0x20)); //等待ADC转换完成
ADC_CONTR &= ~0x20; //清完成标识
ADCValue = ((unsigned int)ADC_RES<<2)+(ADC_RESL>>6);
return ADCValue; //返回ADC结果
}
页:
[1]