OpenEdv-开源电子网

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

同时使用UART和ADC+DMA中断,数据传输错误

[复制链接]

5

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
130
金钱
130
注册时间
2019-7-8
在线时间
34 小时
发表于 2019-8-28 10:51:04 | 显示全部楼层 |阅读模式
void ADC_Config(void)
{
       
        ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE);        //使能ADC和GPIOA时钟  
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置时钟(12MHz),在RCC里面还应配置APB2=AHB时钟72MHz
       
       
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE);        //使能ADC和GPIOA时钟                     
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;        //采集电压的引脚为PA管脚2
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    //模拟输入模式
  GPIO_Init(GPIOA, &GPIO_InitStructure);     //GPIO组

        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        ADC_InitStructure.ADC_ScanConvMode = ENABLE; //关闭通道扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //注意不要使用持续转换模式,否则只要触发一次,//后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;//配置TIM2_CC2为触发源
       
//        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//配置TIM2_CC2为触发源
       
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        ADC_Init(ADC1, &ADC_InitStructure);
               
        ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);
        ADC_DMACmd(ADC1, ENABLE);
       
        ADC_Cmd(ADC1,ENABLE);
        ADC_ExternalTrigConvCmd(ADC1, ENABLE);                        //设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,实际上还是在STM32内部)
       
        ADC_ResetCalibration(ADC1);
        while(ADC_GetResetCalibrationStatus(ADC1));
        ADC_StartCalibration(ADC1);                                          //Start Calibration register
        while(ADC_GetCalibrationStatus(ADC1));                         //waiting for finishing the calibration       

}



void ADC_DMA_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
       
        DMA_InitTypeDef DMA_InitStructure; // 注:ADC为12位模数转换器,只有ADCConvertedValue的低12位有效

         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟
       
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;//串口1是DMA1_4通道 ADC
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//强占0
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//子1
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


        DMA_DeInit(DMA1_Channel1);  
       
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//DMA对应的外设基地址
//   DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//DMA对应的外设基地址
               
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_RegularConvertedValueTab; //内存存储基地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
  DMA_InitStructure.DMA_BufferSize = N;//DMA缓存大小,1个
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //接收多次数据后,目标内存地址后移
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度为16位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位
  DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;//循环转换模式
       
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级高
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//M2M模式禁用
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);         
  DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);//使能传输完成中断
  DMA_Cmd(DMA1_Channel1, ENABLE);

}

void  DMA1_Channel1_IRQHandler(void)         // 使用DMA中断采集数据,不会容易丢失数据
{

//        int a=0;
                int i;
               
           if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
                 {                                        
         DMA_ClearITPendingBit(DMA1_IT_TC1);
                            //自己的中断处理代码 但是记住程序不要太复杂  最好不要超过中断时间
        for(i=0;i<N;i++)
        {
                sum += ADC_RegularConvertedValueTab[i]*3.3/4096.0f;
        }                       
        AVG = sum/N;       
        sum=0;

        }
                // DMA_Cmd(DMA1_Channel1, DISABLE);
}        同时使用串口通讯和ADC+DMA采样,发现串口通讯的数据有时候会发生错误,比如发送02收到0,单使用串口数据不会出错,请问该怎么解决




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

使用道具 举报

4

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
755
金钱
755
注册时间
2018-12-7
在线时间
131 小时
发表于 2019-8-28 17:01:30 | 显示全部楼层
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-10 04:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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