找回密码
 立即注册
楼主: mzh00

STC8G1K08-20,ADC采样的数据不稳定

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 14:39:54 | 显示全部楼层
梁*** 发表于 2025-8-4 13:44
你使用串口发送脚做ADC输入,你是怎么监控ADC值的?

以上测试程序时,只修改target_input_value输入方式,其它代码保持完全一样。  另外adc采样时,先start adc ,  然后检查adc的完成flag,  如果没有完成就去检查usart有没有收到数据,有完成就处理adc的输入值,然后马上开始下一次采样。 另外,测试例子有8/9个nop的指令的,我有测试加上和去掉这些nop,好像都没有影响测试结果。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:276
  • 最近打卡:2025-08-23 14:05:57
已绑定手机

80

主题

2983

回帖

6363

积分

荣誉版主

无情的代码机器

积分
6363
发表于 2025-8-4 14:40:35 | 显示全部楼层
aer*** 发表于 2025-8-4 14:24
你好,这个是要做一个servo的程序,
1.  p3.1采集电位器的电位值, adc使用了10bit的采样,即0-1023,名为  ...

单看这个描述感觉是一个pin上同时用两种外设互相干扰了。
请问输入周期是多少呢,是否尝试分时复用,ADC采集时取消设置串口试下?
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 15:14:21 | 显示全部楼层
erci*** 发表于 2025-8-4 14:40
单看这个描述感觉是一个pin上同时用两种外设互相干扰了。
请问输入周期是多少呢,是否尝试分时复用,ADC ...

输入周期,可以认为就是usart就是输入出一次,9600bps, 然后后面都就不输入了。  我试一下把usart关掉,这个好像只需停timer1,然后取消中断enable,就可以了吧?

两种外设互相干扰,我也是怀疑, 另外  其实我也测试过adc 对于不同channel的采样,也是会冲突的。
测试办法如下:
1. 先对adc的channel 0 (p3.0) 采样,  采样完成16次。
2. 再对adc的channel 1 (p3.1)采样,  采样完成16次.

发现 channel 0  和 channel 1 的值会相互污染。

然后,把次数改成100次,改成下面的样子,就好了。逻辑如下:
1. 先对adc的channel 0 (p3.0) 采样,  采样完成100次。
2. 再对adc的channel 1 (p3.1)采样,  采样完成100次.

点评

还有把REN也可以禁掉。 两个ADC通道互相影响更不应该了。 可以参考开天斧开发板这个例程试下:  详情 回复 发表于 2025-8-4 15:31
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 15:20:10 | 显示全部楼层
梁*** 发表于 2025-8-4 13:44
你使用串口发送脚做ADC输入,你是怎么监控ADC值的?

补充,要是  “当adc采样值 adc_input_value 和 target_input_value相差不过超2时” 这里这个2这个数值,要是改成10, 这个在usart打开的时候也比较稳定,但是效果无法满足设计要求,误差太大了。。。。  也怀能是输入值有问题,只是测试usart打开,target_input_value直接写死512, 后面不修改了。测试结果看到 也是 “到达512附近时,无法停止转动,不停在正反的抖动。”
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:276
  • 最近打卡:2025-08-23 14:05:57
已绑定手机

80

主题

2983

回帖

6363

积分

荣誉版主

无情的代码机器

积分
6363
发表于 2025-8-4 15:31:49 | 显示全部楼层
aer*** 发表于 2025-8-4 15:14
输入周期,可以认为就是usart就是输入出一次,9600bps, 然后后面都就不输入了。  我试一下把usart关掉, ...

还有把REN也可以禁掉。

两个ADC通道互相影响就不应该了。
可以参考开天斧开发板这个例程试下:
08-16路ADC轮询-每路16次ADC转换取中间8次求平均值-串口1返回结果.zip (26.73 KB, 下载次数: 5)
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 18:04:50 | 显示全部楼层
erci*** 发表于 2025-8-4 15:31
还有把REN也可以禁掉。

两个ADC通道互相影响就不应该了。

好的,两个通道相互影响,会不会和我的使用方式有关的? 我看示例是阻塞型的,我改了使用异步的方式,这个会不会有影响?


例子中,是这样的取采样的:
u16        Get_ADC12bitResult(u8 channel)        //channel = 0~15
{
        ADC_RES = 0;
        ADC_RESL = 0;

    ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel;    //启动 AD 转换
    _nop_();
    _nop_();
    _nop_();
    while((ADC_CONTR & 0x20) == 0);   //等待ADC结束
    ADC_CONTR &= ~0x20;     //清除ADC结束标志
    return (((u16)ADC_RES << 8) | ADC_RESL);
}



而我的是采样是这样取的:


u8 current_channel

void start_adc(u8 channel)
{
        ADC_RES = 0;
        ADC_RESL = 0;
        current_channel  = channel;

    ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel;    //启动 AD 转换
     
    _nop_();
    _nop_();
    _nop_();
}



void main()
{
       
        u16 adc_acc;
        u16 ch0_adc = 0;
        u16 ch1_adc = 0;
       
        start_adc(0);
        while(1)
        {

                if((ADC_CONTR & 0x20))
                {

                        ADC_CONTR &= ~0x20;     //清除ADC结束标志
                          adc_acc =  (((u16)ADC_RES << 8) | ADC_RESL);


                        if(current_channel == 0)
                        {
                                if(ch0_adc == 0 )
                                {
                                        ch0_adc = adc_acc;
                                }
                                else
                                {
                                        ch0_adc = (ch0_adc*15 + adc_acc)/16;
                                }
                                  start_adc(1);  //轮到ch1采样
                        }
                        else
                        {

                                if(ch1_adc == 0 )
                                {
                                        ch1_adc = adc_acc;
                                }
                                else
                                {
                                        ch1_adc = (ch1_adc*15 + adc_acc)/16;
                                }

                                start_adc(0); //轮到ch0采样

                        }
                }

                //TODO
                process_other_option();

        }

}

点评

参考这个结构图不支持异步,一个采集完 再切换另一个。 [attachimg]110755[/attachimg]  详情 回复 发表于 2025-8-4 18:11
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:276
  • 最近打卡:2025-08-23 14:05:57
已绑定手机

80

主题

2983

回帖

6363

积分

荣誉版主

无情的代码机器

积分
6363
发表于 2025-8-4 18:11:01 | 显示全部楼层
aer*** 发表于 2025-8-4 18:04
好的,两个通道相互影响,会不会和我的使用方式有关的? 我看示例是阻塞型的,我改了使用异步的方式,这 ...


参考这个结构图不支持异步,一个采集完 再切换另一个。
截图202508041810275520.jpg
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 19:16:13 | 显示全部楼层
erci*** 发表于 2025-8-4 18:11
参考这个结构图不支持异步,一个采集完 再切换另一个。



我也换了一个办法,先采样16个每个,完了再换下一个, 实际只是adc的过程中,我要有机率去做一些其它事情,如计算pwm的宽度,usart的指令处理,更新电机的控制pwm等,
这是异步,而不是并发, 确实这样也会有问题? 我老实先按例子改了试试


u8 current_channel

void start_adc(u8 channel)
{
        ADC_RES = 0;
        ADC_RESL = 0;
        current_channel  = channel;

    ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel;    //启动 AD 转换
     
    _nop_();
    _nop_();
    _nop_();
}



void main()
{
      
        u16 adc_acc;
        u16 ch0_adc = 0;
        u16 ch1_adc = 0;
        u16 num_sample= 0;
      
        start_adc(0);
        while(1)
        {

                if((ADC_CONTR & 0x20))
                {

                        ADC_CONTR &= ~0x20;     //清除ADC结束标志
                          adc_acc =  (((u16)ADC_RES << 8) | ADC_RESL);

                          num_sample ++;
                        if(current_channel == 0)
                        {
                                if(ch0_adc == 0 )
                                {
                                        ch0_adc = adc_acc;
                                }
                                else
                                {
                                        ch0_adc = (ch0_adc*15 + adc_acc)/16;
                                }
                                if(num_sample>16)
                                {
                                     num_sample = 0;
                                    start_adc(1);  //轮到ch1采样
                                }
                                else
                                {
                                      start_adc(0);  
                                }
                        }
                        else
                        {

                                if(ch1_adc == 0 )
                                {
                                        ch1_adc = adc_acc;
                                }
                                else
                                {
                                        ch1_adc = (ch1_adc*15 + adc_acc)/16;
                                }
                                 if(num_sample>16)
                                 {
                                           num_sample = 0;
                                        start_adc(0); //轮到ch0采样
                                 }
                                   else
                                {
                                      start_adc(1);  
                                }

                        }
                }

                //TODO
                process_other_option();

        }

}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-08-12 10:00:26
已绑定手机

2

主题

39

回帖

162

积分

注册会员

积分
162
发表于 2025-8-4 19:16:33 | 显示全部楼层
aer*** 发表于 2025-8-4 19:16
我也换了一个办法,先采样16个每个,完了再换下一个, 实际只是adc的过程中,我要有机率去做一些其它事 ...

这个办法也是有问题的。

点评

“adc的过程中,我要有机率去做一些其它事情” 一个是参考手册里的,中断方式ADC: [attachimg]110757[/attachimg] 另一个,8G手册看了下没DMA,要是换8H8K64U,则可参考库函数例程包的ADC_DMA例程: https://www.  详情 回复 发表于 2025-8-4 21:11
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:276
  • 最近打卡:2025-08-23 14:05:57
已绑定手机

80

主题

2983

回帖

6363

积分

荣誉版主

无情的代码机器

积分
6363
发表于 2025-8-4 21:11:50 | 显示全部楼层
aer*** 发表于 2025-8-4 19:16
这个办法也是有问题的。

“adc的过程中,我要有机率去做一些其它事情”
一个是参考手册里的,中断方式ADC:
截图202508042110295816.jpg


另一个,8G手册看了下没DMA,要是换8H8K64U,则可参考库函数例程包的ADC_DMA例程:
https://www.stcaimcu.com/data/do ... 1U-SOFTWARE-LIB.zip
截图202508042110535149.jpg

三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-8-24 04:09 , Processed in 0.152278 second(s), 100 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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