请教一个ADC采集利用DMA双缓冲的问题

2019-07-20 07:03发布

ADC采集出来的信号一直有问题,我是利用DMA将信号存到一个内存数组,结果内存数组在一半多的时候数据就出现问题了,然后在双缓冲切换时,也会丢失几个点,这个我想的通,但是前面内存数组在一半多数据就全乱了,实在没找到问题,望各位大神解答。以下是代码:
main函数:
#define NUM 1600
int main(void)
{
        float adc_Y=Rel_Value*4096.0/3.3;
        u16 i,t;
        u16 n=0;
        u16 adc_value1[NUM+500];
       u16 adc_value2[NUM+500];       
       u16 b0=0,b1=0;
       u16 max=0;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        delay_init(168);
        uart_init(230400);
        EXTIX_Init();       //初始化外部中断输入
        MYADC1_configure();       
        MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA2_Stream4,DMA_Channel_0,(u32)&ADC1->DR,(u32)&adc_value1,(u32)&adc_value2,NUM);       
        ADC_SoftwareStartConv(ADC1);
        TIM3_Int_Init(10000-1,8400-1);//定时器结束将内存数组的数发出
while(1)       
        {
                        if(DMA_Freebuf_OK==1)
                                {
                                        if(DMA_GetCurrentMemoryTarget(DMA2_Stream4)==0)
                                        {                               
                                                if(n<8000)               
                                                {       
                                                        for(i=0;i<NUM;i++)
                                                        {
                                                                TestData[n]=adc_value2[i];//TestDate为内存数组存储ADC数据。全局变量,大小为10000
                                                                n=n+1;
                                                        }
                                                }
                                        }
                                        else
                                        {       
                                                if(n<8000)                               
                                                {       
                                                        for(i=0;i<NUM;i++)
                                                        {
                                                                TestData[n]=adc_value1[i];
                                                                n=n+1;
                                                        }
                                                }
                                               
                                        }       
                                        DMA_Freebuf_OK=0;                                               
                        }
        }
}

DMA.C:
u8 DMA_Freebuf_OK=0;
u16 TestData[TestData_Len];
void MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA_Stream_TypeDef *DMA_Streamx,u32 chanlx,u32 par,u32 memory0,u32 memory1,u16 ndtr)//(数据流,通道,外设基地址,存储器基地址,传输量,不管是多少位的,传输量只是数据的个数,这里设置为数组的长度)
{
                DMA_InitTypeDef  DMA_InitStructure;
                NVIC_InitTypeDef NVIC_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 = memory0;//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_DoubleBufferModeConfig(DMA_Streamx,(u32)&memory1,DMA_Memory_0);
        DMA_DoubleBufferModeCmd(DMA_Streamx,ENABLE);
        DMA_ClearITPendingBit(DMA2_Stream4,DMA_IT_TCIF4);
        DMA_ITConfig(DMA2_Stream4,DMA_IT_TC,ENABLE);
        DMA_Cmd(DMA_Streamx, ENABLE);       
       
        NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
        NVIC_Init(&NVIC_InitStructure);
       
}


void DMA2_Stream4_IRQHandler()
{
        if(DMA_GetITStatus(DMA2_Stream4,DMA_IT_TCIF4))       
        {                       
                DMA_ClearITPendingBit(DMA2_Stream4,DMA_IT_TCIF4);                       
                DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2);//清满标志       
                while(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)==SET);
                DMA_Freebuf_OK=1;
        }
}



adc.c:
u16 Chanel[Ch_Num];
void MYADC1_configure()//从adc中
{
       
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
        ADC_InitTypeDef ADC_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL ;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
        GPIO_Init(GPIOC,&GPIO_InitStructure);
       
       
        //复位ADC
        ADC_DeInit();
        //配置通用寄存器ADC_CCR
        ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;//单通道
        ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
        ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;//未使用多重ADC模式
        ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//84/4=21M
        ADC_CommonInit(&ADC_CommonInitStructure);
        //配置ADC1
        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       
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10,1, ADC_SampleTime_3Cycles ); //配置通道优先级 SMPR2,SQR3
       
        ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE); //源数据变化时开启DMA传输,CR2
        ADC_DMACmd(ADC1,ENABLE);//使能ADC的DMA传输
        ADC_Cmd(ADC1, ENABLE);
       
       
}

timer:
void TIM3_Int_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
       
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
        TIM_Cmd(TIM3,ENABLE); //使能定时器3
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
        {
                time_c++;
                if(time_c==3)
                {
                        TIM_Cmd(TIM3,DISABLE);
                        {
                                USART_SendData(USART1,0);
                                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                       
                        }
                        for(t=0;t<TestData_Len;t++)
                        {                                               
                                USART_SendData(USART1,(TestData[t]&0xff00)>>8);
                                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                                USART_SendData(USART1,TestData[t]&0xff);
                                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束               
                        }
                        time_c=0;
          }
               
        }
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
正点原子
1楼-- · 2019-07-20 08:12
 精彩回答 2  元偷偷看……
lyl5530330
2楼-- · 2019-07-20 11:37
正点原子 发表于 2018-7-23 09:37
两个大数组放外面,做全局数组,再试试。

对的,我把数组放在串口的.h里面声明全局就可以啦
1208
3楼-- · 2019-07-20 17:00
 精彩回答 2  元偷偷看……
暗蓝
4楼-- · 2019-07-20 22:19
 精彩回答 2  元偷偷看……

一周热门 更多>