找回密码
 立即注册
查看: 108|回复: 17

15W408AS AD采集数据波动大

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-29 08:03:13
已绑定手机

2

主题

17

回帖

56

积分

注册会员

积分
56
发表于 2025-8-26 16:05:32 | 显示全部楼层 |阅读模式
一个简单的AD采集,用ACS712ELCTR-05B-T(XBLW)检测电路电流情况,但结果很打脸,ADC数据波动很大,电路中AD端忘了串电阻,后面加上了,效果也不行。最近用STC单片机做了两个小项目,原本觉得很简单,实际很难受了,串口调试工具也是,有时候会连不上,需要断电重启才有用。

串口调试信息如下:

[15:50:26.718]接收←串口初始化成功
                    ADC_12V_Value: 771
                    
[15:50:27.759]接收←ADC_12V_Value: 769
                    
[15:50:28.769]接收←ADC_12V_Value: 515
                    
[15:50:29.802]接收←ADC_12V_Value: 768
                    
[15:50:30.824]接收←ADC_12V_Value: 2
                    
[15:50:31.836]接收←ADC_12V_Value: 771
                    
[15:50:32.861]接收←ADC_12V_Value: 769
                    
[15:50:33.873]接收←ADC_12V_Value: 1
                    
[15:50:34.899]接收←ADC_12V_Value: 1
                    
[15:50:35.923]接收←ADC_12V_Value: 770
                    
[15:50:36.931]接收←ADC_12V_Value: 771
                    
[15:50:37.952]接收←ADC_12V_Value: 770
                    
[15:50:38.982]接收←ADC_12V_Value: 771
                    
[15:50:40.005]接收←ADC_12V_Value: 515
                    
[15:50:41.014]接收←ADC_12V_Value: 771
                    
[15:50:42.042]接收←ADC_12V_Value: 771
                    
[15:50:43.065]接收←ADC_12V_Value: 771
                    
[15:50:44.077]接收←ADC_12V_Value: 771
                    
[15:50:45.106]接收←ADC_12V_Value: 771
                    
[15:50:46.130]接收←ADC_12V_Value: 771
                    
[15:50:47.137]接收←ADC_12V_Value: 771
                    
[15:50:48.161]接收←ADC_12V_Value: 771
                    
[15:50:49.186]接收←ADC_12V_Value: 771
                    
[15:50:50.208]接收←ADC_12V_Value: 771
                    
[15:50:51.220]接收←ADC_12V_Value: 2
                    
[15:50:52.245]接收←ADC_12V_Value: 770
                    
[15:50:53.269]接收←ADC_12V_Value: 2
                    
[15:50:54.279]接收←ADC_12V_Value: 768
                    
[15:50:55.305]接收←ADC_12V_Value: 1
                    
[15:50:56.331]接收←ADC_12V_Value: 771
                    
[15:50:57.341]接收←ADC_12V_Value: 770
                    
[15:50:58.358]接收←ADC_12V_Value: 1
                    
[15:50:59.385]接收←ADC_12V_Value: 771
                    
[15:51:00.407]接收←ADC_12V_Value: 1
                    
[15:51:01.415]接收←ADC_12V_Value: 771
                    
[15:51:02.442]接收←ADC_12V_Value: 515
                    
[15:51:03.467]接收←ADC_12V_Value: 771
                    
[15:51:04.490]接收←ADC_12V_Value: 769
                    
[15:51:05.502]接收←ADC_12V_Value: 1
                    
[15:51:06.527]接收←ADC_12V_Value: 771
                    
[15:51:07.553]接收←ADC_12V_Value: 1
                    
[15:51:08.563]接收←ADC_12V_Value: 770
                    
[15:51:09.589]接收←ADC_12V_Value: 2
                    
[15:51:10.596]接收←ADC_12V_Value: 2
                    
[15:51:11.621]接收←ADC_12V_Value: 1
                    
[15:51:12.645]接收←ADC_12V_Value: 1
                    
[15:51:13.655]接收←ADC_12V_Value: 2
                    
[15:51:14.680]接收←ADC_12V_Value: 515
                    
[15:51:15.694]接收←ADC_12V_Value: 2
                    
[15:51:16.713]接收←ADC_12V_Value: 771
                    
[15:51:17.740]接收←ADC_12V_Value: 3
                    
[15:51:18.760]接收←ADC_12V_Value: 771
                    
[15:51:19.774]接收←ADC_12V_Value: 771
                    
[15:51:20.795]接收←ADC_12V_Value: 771
                    
[15:51:21.823]接收←ADC_12V_Value: 771
                    
[15:51:22.831]接收←ADC_12V_Value: 3
                    
[15:51:28.952]接收←ADC_12V_Value: 771
                    
[15:51:29.981]接收←ADC_12V_Value: 770
                    
[15:51:30.995]接收←ADC_12V_Value: 771


下面是代码,简单的AD数据采集程序:

#include <stc15.h>
#include <stdio.h>
#include <intrins.h>
// 引脚定义
sbit ADC_12V = P1 ^ 0;
sbit ADC_12V_NEG = P1 ^ 1;
sbit JDQ_12V = P3 ^ 6;
sbit JDQ_12V_NEG = P3 ^ 7;
sbit FMQ = P1 ^ 4;
sbit LED_12V = P1 ^ 3;
sbit LED_12V_NEG = P1 ^ 2;
//定义一些AD采集常量
#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟
/************************** */
// printf重定向到串口
char putchar(char c)
{
    SBUF = c;
    while (!TI)
        ;
    TI = 0;
    return c;
}
void UART1_Init(void)
{
    SCON = 0x50;  // 8位数据,可变波特率
    AUXR |= 0x01; // 串口1选择定时器2为波特率发生器
    AUXR |= 0x04; // 定时器时钟1T模式
    T2L = 0xE0;   // 设置定时初始值
    T2H = 0xFE;   // 设置定时初始值
    AUXR |= 0x10; // 定时器2开始计时
}


/************************** */
void Delay(unsigned int n)
{
    unsigned int x;

    while (n--)
    {
        x = 5000;
        while (x--);
    }
}
void Delay1000us(void)  //@11.0592MHz
{
    unsigned char data i, j;

    _nop_();
    _nop_();
    _nop_();
    i = 11;
    j = 190;
    do
    {
        while (--j);
    } while (--i);
}

void Delay1000ms(void)  //@11.0592MHz
{
    unsigned char data i, j, k;

    _nop_();
    _nop_();
    i = 43;
    j = 6;
    k = 203;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}


/************************** */
unsigned int GetADCResult(unsigned char ch)
{
    unsigned int adc_value;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                        //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC

    adc_value = ( (ADC_RES & 0x03) << 8 ) | ADC_RESL;// 组合10位结果

    return adc_value;                 //返回ADC结果
}

/**************************** */
// IO初始化
void IO_Init(void)
{
    // 设置P1.0 P1.1为模拟输入
    P1ASF = 0X03; // P1.0和P1.1设置为模拟功能
    // 设置P36P37为推挽输出,P3口其他不改变
    P3M0 = 0xC0; // P3.6、P3.7设置为推挽输出
    P3M1 = 0x00; // P3.6、P3.7设置为推挽输出
    // 设置P1.2、P1.3、P1.4为推挽输出(故障灯和蜂鸣器)
    P1M0 = 0x1C; // P1.2、P1.3、P1.4设置为推挽输出
    P1M1 = 0x00; // P1.2、P1.3、P1.4设置为推挽输出

    JDQ_12V = 1;
    JDQ_12V_NEG = 1;
    FMQ = 1;
    LED_12V = 1;
    LED_12V_NEG = 1;
    //初始化AD
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);   
}
// 主函数示例(初始化+发送测试)
void main(void)
{
    IO_Init();
    UART1_Init(); // 初始化串口1
    printf("串口初始化成功\r\n");
   
    while (1)
    {
    //打印P1.0 P1.1的AD值
    printf("ADC_12V_Value: %u\r\n", GetADCResult(0));
   // printf("ADC_12V_NEG_Value: %u\r\n", GetADCResult(1));
    Delay1000ms();
    }
}


SCH_Schematic3_1-电源_2025-08-26.png
回复

使用道具 举报 送花

3

主题

2001

回帖

850

积分

等待验证会员

积分
850
发表于 2025-8-26 16:08:00 | 显示全部楼层
尊敬的用户,您好!

感谢您对国芯人工智能的关注与支持。针对您在使用STC15W408AS单片机进行AD采集时遇到的数据波动问题,以及串口通信不稳定的现象,我们进行了详细分析,并结合实际应用经验为您提供以下专业建议和解决方案。

首先,关于ADC数据波动较大的问题:

1. 电路设计方面  
   您提到在AD采集端未串联电阻,后虽已添加,但效果不佳。这可能涉及以下几个方面:
信号源阻抗匹配:ACS712ELCTR-05B-T传感器输出为电压信号,其输出阻抗较低,但若与ADC输入阻抗不匹配,可能导致采样误差。建议在ADC输入端增加一个适当的RC低通滤波器(如10kΩ电阻+0.1μF电容),以抑制高频噪声。
电源稳定性:ADC采集结果受供电电压影响较大,建议采用独立的稳压电源或在ADC参考电压(Vref)端并联大容量电容(如10μF电解电容)以提高稳定性。
接地方式:确保ADC与传感器共地,避免地线环路引入干扰。可尝试将模拟地与数字地分开处理,再通过一点连接。

2. 软件配置方面  
采样率与转换时间:STC15W408AS的ADC支持多种采样模式,建议根据实际需求选择合适的采样率。过高的采样率可能导致采样窗口过短,无法准确捕捉真实信号。
多次采样平均:在软件中对ADC数据进行多次采样后取平均值,可以有效降低随机噪声带来的波动。例如,每次读取16次ADC值,取其平均值作为最终结果。
ADC校准:部分STC系列MCU支持内部ADC校准功能,建议查阅数据手册并启用相关校准程序,以提升采集精度。

3. 外部干扰因素  
电磁干扰(EMI):若系统工作环境存在强电磁场,可能会对ADC采集造成干扰。建议对敏感电路进行屏蔽处理,或在PCB布局上优化布线,减少信号回路面积。
温度漂移:ACS712ELCTR-05B-T具有一定的温度漂移特性,建议在软件中加入温度补偿算法,或在稳定环境下进行校准。

其次,关于串口通信不稳定的问题:

1. 硬件连接检查  
确保USB转TTL模块与单片机之间的TXD、RXD、GND引脚正确连接,无虚接或短路现象。
使用示波器检测串口信号是否正常,观察是否存在波形失真或噪声干扰。

2. 波特率设置一致性  
确认单片机与调试工具的波特率设置一致(如9600、115200等),且未因时钟源误差导致误码。
若使用内部RC振荡器,建议改用外部晶振以提高时钟精度。

3. 软件逻辑优化  
在串口接收过程中,建议使用缓冲区机制,防止因数据溢出导致丢包或解析错误。
对于异常数据(如突然出现的“2”、“1”等异常值),可增加校验逻辑,判断数据有效性后再进行处理。

综上所述,ADC数据波动和串口通信不稳定问题通常由多方面因素共同作用所致。建议您从电路设计、软件配置和外部环境三方面逐一排查,并结合实际测试数据进行调整优化。

如您有进一步的技术问题或需要更详细的调试指导,欢迎随时联系国芯人工智能技术团队,我们将竭诚为您服务。

祝您项目顺利,技术进步!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-29 08:03:13
已绑定手机

2

主题

17

回帖

56

积分

注册会员

积分
56
发表于 2025-8-26 17:30:43 | 显示全部楼层
10K电阻+0.1uf电容组合,IO配置如下更改,继电器,蜂鸣器这些都没有吸合,万用表测量数据很稳定,但串口数据如下:

[17:29:04.843]接收←串口初始化成功
                    ADC_12V_Value: 1
                    
[17:29:05.881]接收←ADC_12V_Value: 257
                    
[17:29:06.907]接收←ADC_12V_Value: 256
                    
[17:29:07.924]接收←ADC_12V_Value: 1
                    
[17:29:08.949]接收←ADC_12V_Value: 257
                    
[17:29:09.972]接收←ADC_12V_Value: 1
                    
[17:29:10.979]接收←ADC_12V_Value: 769
                    
[17:29:12.004]接收←ADC_12V_Value: 2
                    
[17:29:13.030]接收←ADC_12V_Value: 257
                    
[17:29:14.038]接收←ADC_12V_Value: 1
                    
[17:29:15.060]接收←ADC_12V_Value: 515
                    
[17:29:16.076]接收←ADC_12V_Value: 3
                    
[17:29:17.109]接收←ADC_12V_Value: 3
                    
[17:29:18.118]接收←ADC_12V_Value: 771
                    
[17:29:19.137]接收←ADC_12V_Value: 2
                    
[17:29:20.165]接收←ADC_12V_Value: 1
                    
[17:29:21.184]接收←ADC_12V_Value: 256
                    
[17:29:22.200]接收←ADC_12V_Value: 257
                    
[17:29:23.226]接收←ADC_12V_Value: 3
                    
[17:29:24.236]接收←ADC_12V_Value: 258
                    
[17:29:25.262]接收←ADC_12V_Value: 3
                    

void IO_Init(void)
{
   
    // 设置P36P37为推挽输出,P3口其他不改变
    P3M0 = 0xC0; // P3.6、P3.7设置为推挽输出
    P3M1 = 0x00; // P3.6、P3.7设置为推挽输出
    // 设置P1.2、P1.3、P1.4为推挽输出(故障灯和蜂鸣器)
    P1M0 = 0x1C; // P1.2、P1.3、P1.4设置为推挽输出
    P1M1 = 0x03; // P1.2、P1.3、P1.4设置为推挽输出
// 设置P1.0 P1.1为模拟输入
    P1ASF = 0X03; // P1.0和P1.1设置为模拟功能
   
    JDQ_12V = 1;
    JDQ_12V_NEG = 1;
    FMQ = 1;
    LED_12V = 1;
    LED_12V_NEG = 1;
    //初始化AD
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);   
}



回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:168
  • 最近打卡:2025-09-02 10:14:23

76

主题

6682

回帖

1万

积分

超级版主

积分
14003
发表于 2025-8-26 18:04:42 | 显示全部楼层
1、先示波器看看单片机电源是否纹波大,纹波越小越好,ADC是以VCC为参考的。
2、先不接ACS712的输出,改接VCC-R1-R2-GND经过电阻分压给ADC,比如1K+1K分压到ADC输入,输入对地接10~100nF电容,测试结果看看。

STC15W408AS的10位ADC还是比较稳定的,就是在512读数那里有几个字的误差。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:474
  • 最近打卡:2025-09-03 00:03:38
已绑定手机

153

主题

1857

回帖

2244

积分

金牌会员

积分
2244
发表于 2025-8-26 18:24:33 来自手机 | 显示全部楼层
adc并地试试,之前我也是跳
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:474
  • 最近打卡:2025-09-03 00:03:38
已绑定手机

153

主题

1857

回帖

2244

积分

金牌会员

积分
2244
发表于 2025-8-26 18:25:15 来自手机 | 显示全部楼层
不对,是adc引脚并联个电容到地,,0,1uf就行
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-29 08:03:13
已绑定手机

2

主题

17

回帖

56

积分

注册会员

积分
56
发表于 2025-8-26 19:02:58 | 显示全部楼层
vb2*** 发表于 2025-8-26 18:25
不对,是adc引脚并联个电容到地,,0,1uf就行

不用串电阻吗,我试试
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-29 08:03:13
已绑定手机

2

主题

17

回帖

56

积分

注册会员

积分
56
发表于 2025-8-26 19:03:43 | 显示全部楼层
梁*** 发表于 2025-8-26 18:04
1、先示波器看看单片机电源是否纹波大,纹波越小越好,ADC是以VCC为参考的。
2、先不接ACS712的输出,改接V ...

是啊,之前也没有遇到这种事情,郁闷了
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:474
  • 最近打卡:2025-09-03 00:03:38
已绑定手机

153

主题

1857

回帖

2244

积分

金牌会员

积分
2244
发表于 2025-8-26 19:28:22 | 显示全部楼层
Prin*** 发表于 2025-8-26 19:02
不用串电阻吗,我试试

ADC那个引脚这样,,参考ai8051试验箱那个电路,
截图202508261928035683.jpg
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-29 08:03:13
已绑定手机

2

主题

17

回帖

56

积分

注册会员

积分
56
发表于 2025-8-26 20:53:16 | 显示全部楼层
把ACS712ELCTR-05B-T(XBLW)去掉后,单片机ADC接入5V后,数据很稳,这个苾片怎么会对单片机产生这么大的影响
微信图片_20250826204853_168_138.jpg

点评

示波器看看ACS712的输出。这个芯片我也常用,没遇到过问题。  详情 回复 发表于 2025-8-26 22:43
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-9-3 09:00 , Processed in 0.135907 second(s), 110 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表