shange144k8 发表于 2020-8-23 12:07:18

请教,关于ADC专换值偶尔为0的情况

单片机型号STC8G2k60s4
P0.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); }
        }
}

shange144k8 发表于 2020-8-24 10:24:57

自己先顶一下

XTXB 发表于 2020-8-24 12:51:19

感觉AD转换都要软件滤波才行

shange144k8 发表于 2020-8-24 13:09:23

XTXB 发表于 2020-8-24 12:51
感觉AD转换都要软件滤波才行

是的,如果搞不定只有滤波了

HZKJ 发表于 2020-8-24 14:27:15

真有这种情况,根本就不是靠滤波来搞定的。

hanbing333444 发表于 2020-8-24 17:01:14

用示波器看一下时序对不对,是不是SPI读取的速度太快了,曾遇到过读取的速度太快了或者采样太快会偶尔读到很大值的问题。

shange144k8 发表于 2020-8-24 19:18:06

HZKJ 发表于 2020-8-24 14:27
真有这种情况,根本就不是靠滤波来搞定的。

是啊,我也这么觉得

shange144k8 发表于 2020-8-24 19:18:41

hanbing333444 发表于 2020-8-24 17:01
用示波器看一下时序对不对,是不是SPI读取的速度太快了,曾遇到过读取的速度太快了或者采样太快会偶尔读到 ...

示波器要如何看时序呢,

HZKJ 发表于 2020-8-24 21:22:33

LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者输入信号的波动情况。 一般是芯片问题的可能性极小。

shange144k8 发表于 2020-8-25 08:33:41

HZKJ 发表于 2020-8-24 21:22
LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者 ...

是的,我估计也是电路问题

hanbing333444 发表于 2020-8-25 11:00:35

HZKJ 发表于 2020-8-24 21:22
LZ用的是STC的内部ADC ,用什么示波器 看什么鸟时序啊。。但是倒是可以用示波器看看电源的波动情况,或者 ...

哈哈,是我没注意审题,还以为用的SPI读取的数据。

小李非刀 发表于 2020-8-27 11:28:28

可以向STC技术支持要测试程序。

52HLX 发表于 2020-9-10 22:00:32

这几天我也遇到这样的问题, 用的芯片是 STC8H1K16 系列,用P1.0做为AD输入,刚上电前几秒容易出现采样为0的情况,后面也会出现,但很少。

shange144k8 发表于 2020-9-13 19:50:43

小李非刀 发表于 2020-8-27 11:28
可以向STC技术支持要测试程序。

就是用测试程序测得,已经常用多次取平均的办法

shange144k8 发表于 2020-9-13 19:51:49

52HLX 发表于 2020-9-10 22:00
这几天我也遇到这样的问题, 用的芯片是 STC8H1K16 系列,用P1.0做为AD输入,刚上电前几秒容易出现采样为0 ...

看来不止我遇到
还好是出现零 直接忽略

智涅 发表于 2021-4-25 16:54:47

同样遇到会有小概率出现0

kundi 发表于 2021-4-25 22:57:56

还有一种算法,就是在求平均值的基础上,先通过冒泡排序等方法,查找最大值和最小值,并且将这些最值去掉,然后才计算平均值,以消除极差对整体的影响。

令狐冲 发表于 2021-4-26 08:26:19

kundi 发表于 2021-4-25 22:57
还有一种算法,就是在求平均值的基础上,先通过冒泡排序等方法,查找最大值和最小值,并且将这些最值去掉, ...

滤波是针对信号波动的应对措施,楼主这偶尔出现0值,已经是功能问题了,首先要解决功能问题。
猜测大概率还是程序问题,极小概率是单片机的bug等。

国学芯用 发表于 2021-4-26 08:41:54

问了 R&D, 答复:1,给 MCU 的 内部ADC 模块电源打开后,等个 1ms, 等MCU内部的 ADC 电源稳定后再让 ADC工作; 2,适当加长对外部信号的采样时间,就是对ADC内部采样保持电容的充电或放电时间,时间够,内部才能和外部电势相等。新手这样那样的问题正常
这是个真正达到 10-BIT 精度的 内置 10-BIT ADC

泽文i 发表于 2021-4-30 19:03:39

使用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

shange144k8 发表于 2021-5-3 23:39:46

泽文i 发表于 2021-4-30 19:03
使用ELL库试一下https://gitee.com/zeweni/ELL-8051-LIB
有STC8G的ADC测试例程https://gitee.com/zeweni/EL ...

感谢,我先试下

zllhfl 发表于 2021-5-6 11:52:20

我遇到过偶尔检测4096的现象

泽文i 发表于 2021-5-6 16:12:22

shange144k8 发表于 2021-5-3 23:39
感谢,我先试下

问题解决了吗

zqf441775525 发表于 2023-2-25 20:18:40

我也遇到这个问题了,STC8G2K64S4,官方的测试程序,打印出来ADC的值,偶尔会为0。折腾了好久没搞定

autolog 发表于 2023-2-25 20:58:24

估计是程序的健壮性问题。翻了下我多年前写的代码,ADC转换多了几个步骤,抛砖引玉:

小李非刀 发表于 2023-2-25 22:20:51

偶尔读到0或满量程,硬件问题基本都是因为干扰,包括电源有干扰、输入信号有干扰、电路间有干扰,软件问题就更难判断了。
STC的ADC是开关电容的逼近式ADC,输入有一个采样电容,每次触发ADC都由硬件执行相同的时序,先采样,再做ADC,本身不会出现采样到电压却转换成0的情况。

大家可以测试STC官方的示波器程序,500KHz采样,你可以连续观察正弦波一小时,看看是否有突然变0的,波形是很容易看出来的,反正我没遇到过。

感觉STC推出的好多例子拉低了其应用难度,比如四轴飞控、无刷电机控制、简易示波器、USB通信。。。等等,太多了。

dong889 发表于 2023-7-5 18:07:24

芯片 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]
查看完整版本: 请教,关于ADC专换值偶尔为0的情况