OpenEdv-开源电子网

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

STM32双ADC快速交叉对一个通道采样正弦波出现混乱

[复制链接]

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
发表于 2021-7-9 08:40:33 | 显示全部楼层 |阅读模式
5金钱
#include "bsp_adc.h"
//双ADC采一个通道,提高采样速率 快速交叉模式
//ADC时钟为14M,正常最多只能达到12M,本实验测试了12M与18M
//Tcon=采样时间+12.5周期    设置采样时间最短为1.5周期
uint32_t ADC_DATA=0;
static void ADC_GPIO_Configure(void)
{
           GPIO_InitTypeDef  GPIO_Structure;
           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
           GPIO_Structure.GPIO_Mode = GPIO_Mode_AIN;
           GPIO_Structure.GPIO_Pin = GPIO_Pin_1;          
           GPIO_Init(GPIOC, &GPIO_Structure);
}
void ADC_Init_Configure(void)
{
            ADC_InitTypeDef    ADC_Structure;
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2,ENABLE);

      /*--------------------------ADC1---------------------------------------*/
      ADC_Structure.ADC_Mode = ADC_Mode_FastInterl;
            ADC_Structure.ADC_ScanConvMode = DISABLE;
            ADC_Structure.ADC_ContinuousConvMode = ENABLE;
            ADC_Structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
            ADC_Structure.ADC_DataAlign = ADC_DataAlign_Right;
            ADC_Structure.ADC_NbrOfChannel = 1;
            ADC_Init(ADC1, &ADC_Structure);
            RCC_ADCCLKConfig(RCC_PCLK2_Div6);
            ADC_RegularChannelConfig(ADC1,ADC_Channel_11, 1,ADC_SampleTime_1Cycles5);
      ADC_DMACmd(ADC1, ENABLE);

            /*--------------------------ADC2-------------------------------------------*/
            ADC_Structure.ADC_Mode = ADC_Mode_FastInterl;
            ADC_Structure.ADC_ScanConvMode = DISABLE;
            ADC_Structure.ADC_ContinuousConvMode = ENABLE;
            ADC_Structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
            ADC_Structure.ADC_DataAlign = ADC_DataAlign_Right;
            ADC_Structure.ADC_NbrOfChannel = 1;
            ADC_Init(ADC2, &ADC_Structure);
            RCC_ADCCLKConfig(RCC_PCLK2_Div6);                       
            ADC_RegularChannelConfig(ADC2,ADC_Channel_11, 1,ADC_SampleTime_1Cycles5);
                        ADC_ExternalTrigConvCmd(ADC2,ENABLE);
                       
                        /*------------------ADC1校准----------------------*/
                        ADC_Cmd(ADC1, ENABLE);
            ADC_ResetCalibration(ADC1);
            while(ADC_GetResetCalibrationStatus(ADC1));
            ADC_StartCalibration(ADC1);
            while(ADC_GetCalibrationStatus(ADC1));
                        /*------------------ADC2校准-----------------------*/
            ADC_Cmd(ADC2, ENABLE);
                        ADC_ResetCalibration(ADC2);
            while(ADC_GetResetCalibrationStatus(ADC2));
            ADC_StartCalibration(ADC2);
            while(ADC_GetCalibrationStatus(ADC2));
                        //ADC1软件触发
                        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void  ADC1_DMA_Init(void)
{
            DMA_InitTypeDef  DMA_Structure;
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
            DMA_DeInit(DMA1_Channel1);
      DMA_Structure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));
                        DMA_Structure.DMA_MemoryBaseAddr = (uint32_t)&ADC_DATA;
                        DMA_Structure.DMA_DIR = DMA_DIR_PeripheralSRC;
                        DMA_Structure.DMA_BufferSize = 8;
                        DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
                        DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;
                        DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
                        DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
                        DMA_Structure.DMA_Mode = DMA_Mode_Circular;
                        DMA_Structure.DMA_Priority = DMA_Priority_High;
                        DMA_Structure.DMA_M2M = DMA_M2M_Disable;
      DMA_Init(DMA1_Channel1, &DMA_Structure);

      DMA_Cmd(DMA1_Channel1, ENABLE);
}
void ADC_InitS(void)
{
            ADC_GPIO_Configure();
            ADC1_DMA_Init();
            ADC_Init_Configure();
            
}

//main函数
#include "bsp_adc.h"
#include "stm32f10x.h"
#include "bsp_usart.h"
extern uint32_t ADC_DATA;
int main(void)
{       
          uint16_t ADC1_DATA;
          uint16_t ADC2_DATA;
          double a,b;
          
          uint8_t i=0;
          USART1_Config();
          ADC_InitS();
          
          while(1)
                {          
                                ADC2_DATA = (uint16_t)((ADC_DATA>>16)&0xfff);
                                ADC1_DATA = (uint16_t)((ADC_DATA)&0xfff);
                          a = (double)(ADC2_DATA/4096*3.3);
                        b = (double)ADC1_DATA/4096*3.3;       
                        printf("%f\r",a);
                          
                          
                                printf("%f\r",b);
                                  
                }
            
}





正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 12:04:46 | 显示全部楼层
cfyasdf1234 发表于 2021-7-9 11:58
确实,确实,那他为什么不能达到手册上所说的1MHz左右的采样率呢?我到底是哪里配置错了呢?采样为什么这 ...

采样率是能达到1MHz的,只是你发送得太慢了,ADC_DATA在你两次发送之间已更新了N次。
可利用DMA将采样数据存入一个长一些的数组,采集完成后你再读取数组慢慢发出来。
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 08:42:03 | 显示全部楼层
采样正弦波的时候用EXcel画图不是正弦波,搞了一天不知道问题出在哪里
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 08:42:38 | 显示全部楼层
采集正弦波结果出现的不是正弦波,不知道问题出在哪?
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 11:18:27 | 显示全部楼层
ADC2_DATA/4096这里已经丢失了精度,建议先别作处理,直接发送ADC2_DATA。
不要说“不是正弦波”,得把数据拿出来看。
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 11:47:31 | 显示全部楼层
LcwSwust 发表于 2021-7-9 11:18
ADC2_DATA/4096这里已经丢失了精度,建议先别作处理,直接发送ADC2_DATA。
不要说“不是正弦波”,得把数 ...

大佬,我把ADC2_DATA和ADC1_DATA都由16进制转10进制输出没除以4096,然后直接串口发送出现如下波形,这个有点规律但是还是看不出来,感谢大佬指点
111.png
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 11:53:11 | 显示全部楼层
cfyasdf1234 发表于 2021-7-9 11:47
大佬,我把ADC2_DATA和ADC1_DATA都由16进制转10进制输出没除以4096,然后直接串口发送出现如下波形,这个 ...

波形还是有的。
假如串口波特率9600,printf发送10个字符约耗时10ms,相当于采样率为100Hz,那么你的正弦波频率要在10Hz以内才能好看。
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 11:58:31 | 显示全部楼层
LcwSwust 发表于 2021-7-9 11:53
波形还是有的。
假如串口波特率9600,printf发送10个字符约耗时10ms,相当于采样率为100Hz,那么你的正 ...

确实,确实,那他为什么不能达到手册上所说的1MHz左右的采样率呢?我到底是哪里配置错了呢?采样为什么这么慢啊
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 12:08:34 | 显示全部楼层
LcwSwust 发表于 2021-7-9 12:04
采样率是能达到1MHz的,只是你发送得太慢了,ADC_DATA在你两次发送之间已更新了N次。
可利用DMA将采样数 ...

噢噢,好的,我下午试试,太感谢大佬了,成功了马上告诉你
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 14:32:58 | 显示全部楼层
LcwSwust 发表于 2021-7-9 12:04
采样率是能达到1MHz的,只是你发送得太慢了,ADC_DATA在你两次发送之间已更新了N次。
可利用DMA将采样数 ...

大佬,我刚才按照你说的做了结果出现了这样的效果,采的是1k,DMA传递数组变成了1024个
333.png
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 14:37:45 | 显示全部楼层
cfyasdf1234 发表于 2021-7-9 14:32
大佬,我刚才按照你说的做了结果出现了这样的效果,采的是1k,DMA传递数组变成了1024个

哦,波形变好看了,不错不错。
信号频率很高?
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 14:44:04 | 显示全部楼层
LcwSwust 发表于 2021-7-9 14:37
哦,波形变好看了,不错不错。
信号频率很高?

不是啊,刚1K,感觉是ADC1与ADC2的采样的相位问题,但是我看手册说:最大允许采样时间<7个ADCCLK周期,那就只能用1.5那个了,7.5那个就大于7了
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 14:50:49 | 显示全部楼层
cfyasdf1234 发表于 2021-7-9 14:44
不是啊,刚1K,感觉是ADC1与ADC2的采样的相位问题,但是我看手册说:最大允许采样时间

ADC由什么触发?
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 14:56:12 | 显示全部楼层
LcwSwust 发表于 2021-7-9 14:50
ADC由什么触发?

麻烦大佬指教了
33333.png
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 15:18:37 | 显示全部楼层

哦,是连续转换模式,应该没问题。
我也有解决不了的问题。
看看你的数据处理呢?能否测一下从开始到DMA结束的时间?有示波器吧?
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 15:26:37 | 显示全部楼层
LcwSwust 发表于 2021-7-9 15:18
哦,是连续转换模式,应该没问题。
我也有解决不了的问题。
看看你的数据处理呢?能否测一下从开始 ...

是用debug测量吗?测量数组满的时候的时间?具体用示波器怎么测量啊。
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-9 15:52:35 | 显示全部楼层
cfyasdf1234 发表于 2021-7-9 15:26
是用debug测量吗?测量数组满的时候的时间?具体用示波器怎么测量啊。

很常用的方法:IO输出置高、等待DMA完成、IO输出低,示波器测这个IO。
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-9 16:22:39 | 显示全部楼层
LcwSwust 发表于 2021-7-9 15:52
很常用的方法:IO输出置高、等待DMA完成、IO输出低,示波器测这个IO。

刚测完是25.10us,不太会用示波器
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-10 09:15:32 | 显示全部楼层
LcwSwust 发表于 2021-7-9 15:18
哦,是连续转换模式,应该没问题。
我也有解决不了的问题。
看看你的数据处理呢?能否测一下从开始 ...

DMA得调成DMA_Mode_Normal模式,连续转换会发生混叠,我也不知道为啥,之后的话能测1K-300k左右,1K以下采集不到一个周期,在300多k会发生混叠,昨天麻烦大佬指教了
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8644
金钱
8644
注册时间
2020-5-11
在线时间
4098 小时
发表于 2021-7-10 09:45:51 | 显示全部楼层
cfyasdf1234 发表于 2021-7-10 09:15
DMA得调成DMA_Mode_Normal模式,连续转换会发生混叠,我也不知道为啥,之后的话能测1K-300k左右,1K以下 ...

不错不错,连续转换的话,你读数组时它仍在写数组,所以会混。
专治疑难杂症
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-10-26
在线时间
15 小时
 楼主| 发表于 2021-7-10 10:34:27 | 显示全部楼层
LcwSwust 发表于 2021-7-10 09:45
不错不错,连续转换的话,你读数组时它仍在写数组,所以会混。

感谢大佬这两天的指导了,我刚才把DMA来回开关能差不多达到效果,但是不知道这样有断点的话对FFT会不会有影响。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-23 15:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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