lyl5530330 发表于 2018-5-24 22:43:34

新手求助,多重ADC采集单通道通过DMA传输到内存数组中的...

本帖最后由 lyl5530330 于 2018-5-24 22:45 编辑

各位大神,小弟初学stm32,现在在项目中遇到一个问题,比如说我采集一个信号,只有一个通道,通过ADC123多重采样通过DMA传输到数组中,再通过串口输出可见,我采的是一个2V的直流电平,采到的图在附件,由图可以看出采到的数据有问题,大神能帮我看下程序嘛

以下是main函数:
#define NUM 100
int main(void)
{
      u16 adcx1,adcx2,adcx3;
      u8 i,t,z=0;
      u32 adc_value;
      delay_init(168);
      uart_init(115200);
      LED_Init();
      MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA2_Stream0,DMA_Channel_0,(u32)&ADC->CDR,(u32)adc_value,NUM);
      MYADC_configure();

      
while(1)      
{
      
      for(i=0;i<NUM;i++)
                {                        
                        adcx1=adc_value&0xffff0000>>16;
                        USART_SendData(USART1,(adcx1&0xff00)>>8);
                        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                        USART_SendData(USART1,adcx1&0xff);
                        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                        
                        adcx2=adc_value&0xffff;
                        USART_SendData(USART1,(adcx2&0xff00)>>8);
                        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                        USART_SendData(USART1,adcx2&0xff);
                        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
         }
      
                delay_ms(2000);
          LED0=!LED0;
}
      
}
以下是adc配置函数#include "adc.h"
#include "sys.h"

void MYADC_configure()//从adc中
{
       
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
        ADC_InitTypeDef ADC_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3|RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2, ENABLE);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL ;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
       
        //复位ADC
        ADC_DeInit();
        //配置通用寄存器ADC_CCR
        ADC_CommonInitStructure.ADC_Mode=ADC_TripleMode_Interl;//三重交替模式
        ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
        ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_2;//DMA模式2
        ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//84/4=21M
        ADC_CommonInit(&ADC_CommonInitStructure);
        //配置ADC3
        ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率12位
        ADC_InitStructure.ADC_ScanConvMode=DISABLE;//关闭扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换 CR2
        ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//不采用边沿触发
        ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右对齐
        ADC_InitStructure.ADC_NbrOfConversion=1;//采样通道1个
        ADC_Init(ADC1,&ADC_InitStructure);
       
        ADC_Init(ADC2,&ADC_InitStructure);

        ADC_Init(ADC3,&ADC_InitStructure);
       
        //始能ADC       
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_480Cycles ); //配置通道优先级 SMPR2,SQR3
        ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_480Cycles ); //配置通道优先级 SMPR2,SQR3
        ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 1, ADC_SampleTime_480Cycles ); //配置通道优先级 SMPR2,SQR3
       
        ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
       
        ADC_Cmd(ADC1, ENABLE);
        ADC_Cmd(ADC2, ENABLE);
        ADC_Cmd(ADC3, ENABLE);

       
        ADC_SoftwareStartConv(ADC1);
        ADC_SoftwareStartConv(ADC2);
        ADC_SoftwareStartConv(ADC3);
       

       
}

<span style="background-color: rgb(255, 255, 255);">
</span>
以上就是代码部分

lyl5530330 发表于 2018-5-24 22:46:32

DMA的不知道为啥没显示,我补充一下:#include "dma.h"
#include "sys.h"

void MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA_Stream_TypeDef *DMA_Streamx,u32 chanlx,u32 par,u32 memory,u16 ndtr)//(数据流,通道,外设基地址,存储器基地址,传输量,不管是多少位的,传输量只是数据的个数,这里设置为数组的长度)
{
                DMA_InitTypeDefDMA_InitStructure;
       
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
        }
DMA_DeInit(DMA_Streamx);
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
               
               /* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = chanlx;//通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址,S0PAR
DMA_InitStructure.DMA_Memory0BaseAddr = memory;//DMA 存储器地址 S0M0AR
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralToMemory ;//外设到存储器
DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量 ,NDTR
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式,S0CR
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式,S0CR
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 循环模式,S0CR
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级,S0CR
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
        DMA_Cmd(DMA_Streamx, ENABLE);
       
}




wenyangzeng 发表于 2018-5-25 07:22:49

本帖最后由 wenyangzeng 于 2018-5-25 16:25 编辑

1、楼主在主循环里不停地发送数据,如果ADC未转换结束,则可能会发送错误的数据。
2、只使用1个ADC,为何要打开3个ADC(ADC1、ADC2、ADC3)且使能三重交替模式?
3、DMA配置貌似未配置完整。ST官方代码可以参考:

MrJiu 发表于 2018-5-25 09:48:28

直接使用官方的hal库,然后用cube配置岂不是更加好;P;P;P

wolfgang2015 发表于 2018-5-25 10:03:35

1、ADC参考电压没对导致结果偏大
2、先不要测变化量,先要测个归零量,稳定量,避免因采样的方式带来的误差
3、直流电平最好选择电池,开关电源有波纹,并不是想象的那么平;
4、幅度大于波纹,看看是否采样过快或过慢,造成数据不准
5、3个ADC都送一个DMA, 但DAM设置用的是 DMA_PeripheralInc = DMA_PeripheralInc_Disable

这与 “如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_Enable;” 不同。

西边的云彩 发表于 2018-5-25 10:38:54

正好需要,感谢

lyl5530330 发表于 2018-5-25 14:15:10

wenyangzeng 发表于 2018-5-25 07:22
1、楼主在主循环里不停地发送数据,如果ADC未转换结束,则可能会发送错误的数据。
2、只使用1个ADC,为何要 ...

谢谢,您发的这个附件我下载下来是空的。。。。
我以为三个ADC都要打开转换所以就打开三个ADC软件转换了。
那这个循环里面该怎么写呢?有没有一个函数是开启/关闭从ADC-CDR寄存器的DMA传输的呢,就像ADC_DMACmd(ADC3,DISABLE);在使用串口传输的时候就不让DMA取数了

lyl5530330 发表于 2018-5-25 14:15:36

MrJiu 发表于 2018-5-25 09:48
直接使用官方的hal库,然后用cube配置岂不是更加好

怎么用啊。。新手表示用不来:'(

lyl5530330 发表于 2018-5-25 14:16:20

wolfgang2015 发表于 2018-5-25 10:03
1、ADC参考电压没对导致结果偏大
2、先不要测变化量,先要测个归零量,稳定量,避免因采样的方式带来的误差 ...

嗯嗯,我改用一下外设递增的模式试一下

lyl5530330 发表于 2018-5-25 14:17:20

本帖最后由 lyl5530330 于 2018-5-25 14:19 编辑

wolfgang2015 发表于 2018-5-25 10:03
1、ADC参考电压没对导致结果偏大
2、先不要测变化量,先要测个归零量,稳定量,避免因采样的方式带来的误差 ...
但是三个ADC转换的数据都是存在ADC-CDR寄存器中的呀,这个也需要递增吗,如果改成外设递增的话那么传出来的数就全是0了
页: [1] 2
查看完整版本: 新手求助,多重ADC采集单通道通过DMA传输到内存数组中的...