OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3448|回复: 28

如何1S内刷新一次AD转换值

[复制链接]

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
发表于 2020-6-27 13:24:19 | 显示全部楼层 |阅读模式
1.求助如何1S内刷新一次AD值,

2.原子哥的AD转换程序中ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件启动而不是外部启动
如果我要改成用定时器200ms取10次求平均值该如何写
谢谢
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 16:24:13 | 显示全部楼层
请高手帮下啊,如何写啊
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2020-6-27 17:06:34 | 显示全部楼层
定时器触发就好了
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 19:31:11 | 显示全部楼层
能帮忙写一下吗?
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 19:34:05 | 显示全部楼层
void  Adc_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );          //ê1ÄüADC1í¨μàê±Öó
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //éèÖÃADC·ÖÆμòò×ó6 72M/6=12,ADC×î′óê±¼ä2»Äü3¬1y14M

        //PA1 ×÷ÎaÄ£Äaí¨μàêäèëòy½Å                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //Ä£Äaêäèëòy½Å
        GPIO_Init(GPIOA, &GPIO_InitStructure);       

        ADC_DeInit(ADC1);  //¸′λADC1

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC1¤×÷Ä£ê½:ADC1oíADC21¤×÷Ôú¶àá¢Ä£ê½
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //Ä£êy×a»»1¤×÷Ôúμ¥í¨μàÄ£ê½
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //Ä£êy×a»»1¤×÷Ôúμ¥′Î×a»»Ä£ê½
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//是不是这个地方要修改成定时器触发啊        //×a»»óéèí¼t¶ø2»êÇía2¿′¥·¢Æô¶ˉ
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADCêy¾Yóò¶ÔÆë
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //Ë3Dò½øDD1æÔò×a»»μÄADCí¨μàμÄêyÄ¿
        ADC_Init(ADC1, &ADC_InitStructure);        //¸ù¾YADC_InitStructÖDÖ¸¶¨μÄ2Îêy3õê¼»ˉíaéèADCxμļÄ′æÆ÷   

  
        ADC_Cmd(ADC1, ENABLE);        //ê1ÄüÖ¸¶¨μÄADC1
       
        ADC_ResetCalibration(ADC1);        //ê1Äü¸′λD£×¼  
         
        while(ADC_GetResetCalibrationStatus(ADC1));        //μè′y¸′λD£×¼½áêø
       
        ADC_StartCalibration(ADC1);         //¿aÆôADD£×¼

        while(ADC_GetCalibrationStatus(ADC1));         //μè′yD£×¼½áêø

//        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //ê1ÄüÖ¸¶¨μÄADC1μÄèí¼t×a»»Æô¶ˉ1|Äü

}       
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 19:35:15 | 显示全部楼层
这个是正点原子的源码是不是软件触发要修改成定时器触发啊,除了这个还有哪里要修改啊
回复 支持 反对

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13129
金钱
13129
注册时间
2012-11-26
在线时间
3814 小时
发表于 2020-6-27 21:07:39 | 显示全部楼层
用DMA吧
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 22:33:22 | 显示全部楼层
我想问下,我现在AD全是采用软件触发方式,然后我用一个定时器定时5ms溢出一次,在定时器中断里面5ms一次AD转换可以吗?

void TIM5_IRQHandler(void)//定时器中断时间为2ms
{
  
        if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)  //¼ì2éTIM6¸üDÂÖD¶Ï·¢éúóë·ñ
        {
                       
        }
        TIM_ClearITPendingBit(TIM5, TIM_IT_Update);  //Çå3yTIMx¸üDÂÖD¶Ï±êÖ¾
                                                                                                                                                                                                                                                                                                       
   if(flag_600ms==0)
   {
          time3++;
          if(time3==300)
         {
              time3=0;
             flag_600ms=1;                               
      }

}
       
}       
   
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-27 22:39:56 | 显示全部楼层
我用软件触发AD转换,比如239.5个周期转换一次,转换时间为239.5+12.5=21us,取5次平均值,然后把这个adc=Get_Adc_Average(ADC_Channel_0,5);放到我做的一个
   定时器5ms溢出一次,把adc=Get_Adc_Average(ADC_Channel_0,5);放到这个定时器中断里面让这个AD转换,5ms就中断一次,这个思路可行吗?
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-28 08:47:55 | 显示全部楼层
我想问下我用软件触发AD转换,然后再把转换的结果ad=Get_Adc_Average(ADC_Channel_0,10);放入定时器中断里面,比如我的定时器中断为5ms中断溢出一次,这样做能达到5ms扫描更新一次AD值吗
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-28 08:48:25 | 显示全部楼层
我想问下我用软件触发AD转换,然后再把转换的结果ad=Get_Adc_Average(ADC_Channel_0,10);放入定时器中断里面,比如我的定时器中断为5ms中断溢出一次,这样做能达到5ms扫描更新一次AD值吗
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-28 08:49:18 | 显示全部楼层
我想问下我用软件触发AD转换,然后再把转换的结果ad=Get_Adc_Average(ADC_Channel_0,10);放入定时器中断里面,比如我的定时器中断为5ms中断溢出一次,这样做能达到5ms扫描更新一次AD值吗
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-28 13:20:59 | 显示全部楼层
hlphzy123456 发表于 2020-6-28 08:49
我想问下我用软件触发AD转换,然后再把转换的结果ad=Get_Adc_Average(ADC_Channel_0,10);放入定时器中断里 ...

定时器触发AD转换我已经做好了,现在有另外一个问题困扰我,1.用定时器触发AD转换比如1S触发一次然后用DMA运输保存读取数据,读取的AD值是很准,但是我想要当AD值大于1024时执行LED1=1,小于1024,LED2=1。我用串口打印的话小灯的显示一直为0,用软件触发启动AD转换就能正常,不知道什么原因,还请大神出来帮解决下啊,谢谢
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-28 20:55:31 来自手机 | 显示全部楼层
没人帮看下吗?大神们出来下啊
回复 支持 反对

使用道具 举报

10

主题

271

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1236
金钱
1236
注册时间
2015-5-14
在线时间
352 小时
发表于 2020-6-28 21:56:29 来自手机 | 显示全部楼层
没看懂,你的问题是啥,给你思路如下:1、确定AD的触发源,如果AD触发源是定时器触发,则没啥好说的,定时器设置1s触发即刻;如果AD触发源是软件触发,也好做,把定时器设置1s,然后在定期中断函数里面调用AD触发函数即可;2、AD值刷新,没啥可说的,在AD中断函数里面(经过计算)给它赋值就可以了;3、AD值判断,有两种思路,看你怎么做了,可以在main里面不停地对AD值判断;也可以在AD中断里面,对AD值赋值后,进行判断;
回复 支持 反对

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
发表于 2020-6-29 06:46:36 | 显示全部楼层
用DMA循环扫描到数组,定时去取数组来做平均值就可以了
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-29 10:21:23 | 显示全部楼层
非常感谢,准备先用软件触发,然后把得到的AD值放入定时器中断里面每1S中断一次,就能得到1S刷新一次AD值了对吗
回复 支持 反对

使用道具 举报

7

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2017-4-27
在线时间
25 小时
发表于 2020-6-29 11:02:17 | 显示全部楼层
用DMA循环扫描到数组,定时去取数组来做平均值就可以了
回复 支持 反对

使用道具 举报

0

主题

104

帖子

0

精华

高级会员

Rank: 4

积分
724
金钱
724
注册时间
2015-5-23
在线时间
137 小时
发表于 2020-6-29 16:47:08 | 显示全部楼层
用DMA循环扫描到数组,定时去取数组来做平均值就可以了
用这个方式就行
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-29 18:33:52 | 显示全部楼层
我用AD来做采集,采集到的AD值用示波器看是很杂的波形,这样的波形我如何处理AD转换才能使的单片机检测到AD值后再执行相应的程序平滑些啊
1.png
回复 支持 反对

使用道具 举报

10

主题

271

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1236
金钱
1236
注册时间
2015-5-14
在线时间
352 小时
发表于 2020-6-29 18:58:26 来自手机 | 显示全部楼层
硬件上AD端口做一个低通滤波器,软件上做低通滤波算法!
回复 支持 反对

使用道具 举报

10

主题

271

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1236
金钱
1236
注册时间
2015-5-14
在线时间
352 小时
发表于 2020-6-29 18:59:37 来自手机 | 显示全部楼层
https://blog.csdn.net/wuhenyouyuyouyu/article/details/38518023
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-29 21:42:28 来自手机 | 显示全部楼层
谢谢啊,还想问下如何1秒内将Ad平均100次,取平均值并和前一个1秒内取的Ad平均值比较昵
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-29 21:59:19 来自手机 | 显示全部楼层
网页我看了,非常有用,但是我不知道这个函数要如何加进程序中,比如限幅度滤波法中的char Value如何判断它是上次采样有效值
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-30 11:49:42 | 显示全部楼层
#define A 10

uchar Value;    //上次采样有效值

uchar AmplitudeLimiterFilter()

{

    uchar NewValue,ReturnValue;

    NewValue=GetAD();          //本次采样值

    if(((NewValue-Value)>A)||((Value-NewValue)>A)))

    ReturnValue=Value;

    else ReturnValue=NewValue;

    return(ReturnValue);

}

int man
{
AmplitudeLimiterFilter();
X=float(ReturnValue);
if(X>4096/2)执行一个动作;
if(X<4096/2)执行一个动作;

}

现在的情况是AD值根本检查不到了,也不响应if语句,哪里错了啊,急啊
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-30 11:50:35 | 显示全部楼层
无痕幽雨 发表于 2020-6-29 18:59
https://blog.csdn.net/wuhenyouyuyouyu/article/details/38518023

在吗?帮我看下哪里错了啊
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-6-30 20:43:44 | 显示全部楼层
无痕幽雨还在吗?能帮我看看吗?uint value;
uint temp,temp1;

uint filter()
{
   uint  new_value;        init_adc() ;
   new_value = (uint)(ee*1.024);//ADgeshi(0);
   if ( ( new_value - value > A ) || ( value - new_value > A ))
   return value;
   return new_value;
        
}

void main()
{

        UART_Init(); //串口初始化
        TI = 1;//使用printf()puts()前都应软件置位TI = 1;
    n=1;
        while(1)
        {
                AD();
                temp=(uint)(ee*1.024);
                temp1= filter();
                //n=n+1;
                printf(" temp=%d\n", temp);
                printf(" temp1=%d\n", temp1);

        }       
}我用串口打印temp有值,temp1确实不执行一直为0,不知道为什么啊
2.png
回复 支持 反对

使用道具 举报

10

主题

271

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1236
金钱
1236
注册时间
2015-5-14
在线时间
352 小时
发表于 2020-6-30 22:10:32 | 显示全部楼层
这只是一个最基本的思路,和实用还有差距。需要你去调;需要多中算法组合。
  1. static        uint32_t   s_wAdOldData;

  2. uint32_t   filter(uint32_t wData)
  3. {
  4. #define        A        30
  5.         if(abs((s_wAdOldData - wData)) > A){
  6.                 return s_wAdOldData;
  7.         }else{
  8.                 s_wAdOldData = wData;//新值有效,则更新旧值               
  9.         }
  10.         return wData;
  11. }


  12. void main(void)
  13. {
  14.         //初始化
  15.         。 。 。
  16.        
  17.         //初始化AD值
  18.         s_wAdOldData = AD采样值;
  19.        
  20.         while(1){
  21.                 用户程序
  22.         }
  23. }
复制代码
30年众生牛马,60年诸佛龙象!
回复 支持 反对

使用道具 举报

11

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-5-23
在线时间
26 小时
 楼主| 发表于 2020-7-2 11:38:02 | 显示全部楼层
无痕幽雨非常感谢啊,还要麻烦你帮我再看下下面这个我理解对吗

#define N 12;
u16 sum,v;
float f;
u16 ArithmeticalAverageValueFilter()
{
        u16 i,Value;
        sum=0;
        for(i=0;i<N;i++)
        {
                sum+=Get_Adc_Average(ADC_Channel_7,10);
        }
        Value=sum/N;
        return(Value);
}

int main()
{
初始化程序;
while(1)
{
sum=Get_Adc_Average(ADC_Channel_7,10);//想法是先让sum的值等于AD转换值
v=ArithmeticalAverageValueFilter();//这个是求平均的值
f=float(v)*1.0;
}


}
再麻烦下,我这样写的话v是不是就是Get_Adc_Average(ADC_Channel_7,10)取12数的平均值了啊;
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-18 19:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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