OpenEdv-开源电子网

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

【求救】STM32的ADC配合DMA发现采集点和计算不符

[复制链接]

2

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-8-21
在线时间
13 小时
发表于 2016-4-28 19:20:04 | 显示全部楼层 |阅读模式
5金钱
想用STM32做ADC采集,然后用DMA发到串口在电脑上显示出来,但是发现通过计算进行的ADC配置和实际效果不相符
我用的是ADC1 ADC时钟频率12M 然后采样周期选的是55.5 用了DMA中断,去采集1Khz的PWM波,每次采200个点


按照手册里的计算 TCONV = 采样时间+ 12.5个周期    一次采样的时间为200*(1/12M)*(55.5+12.5)=1.13ms 差不多该是PWM波的一周期多,但是我把数组拉出来后发现这两个点差不多包含了有8个PWM波周期了...
不清楚是不是配置哪里出问题了还是DMA没用好,希望大神们指点下。




[mw_shl_code=c,true]//*************************************************************************
// 函数名        :GPIO_Configuration
// 描述                :引脚配置
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void GPIO_Configuration(void)
{

  GPIO_InitTypeDef  GPIO_InitStructure;
        
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD |RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB
                         |RCC_APB2Periph_AFIO |RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC ,ENABLE);         
               
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);                       //使能串口5时钟
        
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                                                                        //配置低速ADC时钟等于SYSCLK/6      12M
        
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;             //管脚12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用推挽输出
  GPIO_Init(GPIOC, &GPIO_InitStructure);                //TX5初始化
        

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;              //管脚2
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
  GPIO_Init(GPIOD, &GPIO_InitStructure);                 //RX5初始化
        
  
  GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE); //Timer2部分重映射  TIM2_CH3->B10            
     //设置该引脚为复用输出功能,输出TIM2 CH3的PWM脉冲波形        GPIOB.10
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM2_CH3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
        
        //PB1 作为模拟通道9输入引脚  CP输入                       
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

//*************************************************************************
// 函数名        :ADC_Init1
// 描述                :ADC初始化  ADC1 ch9   PB1
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void ADC_Init1(void)
{
  ADC_InitTypeDef ADC_InitStructure;//ADC初始化结构体声明
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式 对应双模式
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;                   //关闭扫描模式
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC外部开关,SWSTART
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式
  ADC_InitStructure.ADC_NbrOfChannel = 1;//开启通道数,1个
  ADC_Init(ADC1, &ADC_InitStructure);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5);//ADC通道组, 第9个通道 采样顺序1
        
  ADC_DMACmd(ADC1, ENABLE);        //使能ADC1和DMA的链接
        
  ADC_Cmd(ADC1, ENABLE); //使能ADC1
   
  ADC_ResetCalibration(ADC1);        //重新校准

  while(ADC_GetResetCalibrationStatus(ADC1));//等待重新校准完成

  ADC_StartCalibration(ADC1);//开始校准

  while(ADC_GetCalibrationStatus(ADC1));//等待校准完成

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);        //连续转换开始,ADC通过DMA方式不断的更新RAM区。
}
//*************************************************************************
// 函数名        :DMA_Init1
// 描述                :DMA初始化
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void DMA_Init1(void)
{
        DMA_InitTypeDef DMA_InitStructure;      //DMA初始化结构体声明
        
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                                                                                                                        // 使能 DMA 时钟
        
        DMA_DeInit(DMA1_Channel1);                                                                                                                                                                                                                        //开启DMA1第一通道
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;                                                                            //DMA对应的外设基地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;                                   //内存存储基地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                                                                                                        //DMA的转换模式为SRC模式,由外设搬移到内存
  DMA_InitStructure.DMA_BufferSize = USART_REC_LEN;                                                                                                                                                                   //DMA缓存大小,120个,单位为DMA_MemoryDataSize
  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_Normal;                                                                                                                                   //转换模式,非循环缓存模式。
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                                                                                        //DMA优先级高
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                                                                                          //M2M模式禁用
        
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);      

        DMA_ClearFlag(DMA1_FLAG_TC1);
        
  DMA_ITConfig( DMA1_Channel1, DMA1_IT_TC1, ENABLE );                                                                                                                        //开通道传输完成标志                                                                                                

  DMA_Cmd(DMA1_Channel1, DISABLE);                                                                                                                                                                                                        //使能DMA1通道1
        
}

//*************************************************************************
// 函数名        :UART_Init
// 描述                :串口初始化
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void UART_Init(void)
{
  USART_InitTypeDef USART_InitStructure;                                                                                                   //串口初始化结构体声明
  USART_InitStructure.USART_BaudRate = 9600;                                                                                         //波特率9600
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;                                                         //字长8位
  USART_InitStructure.USART_StopBits = USART_StopBits_1;                                                                 //1位停止字节
  USART_InitStructure.USART_Parity = USART_Parity_No;                                                                         //无奇偶校验
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;                 //无流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                                                 //打开Rx接收和Tx发送功能
        
        
        USART_Init(UART5, &USART_InitStructure);                        

        USART_Cmd(UART5, ENABLE);
        
        USART_ClearFlag(UART5,USART_FLAG_RXNE);
        
  USART_ITConfig(UART5, USART_IT_RXNE, DISABLE);
        
}
//*************************************************************************
// 函数名        :NVIC_Configuration
// 描述                :中断配置
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure the NVIC Preemption Priority Bits */  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  /* Enable the USART5 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  /* Enable the DMA1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;        //DMA通道1中断允许
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  

        
}
//*************************************************************************
// 函数名        :TIM3_Configuration
// 描述                :定时器3初始化
// 入口                :
// 出口                :
// 返回                :
//*************************************************************************
void TIM3_Configuration (void)
{  
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
        
  TIM_TimeBaseStructure.TIM_Period = 49;       //自动装载的计数值 计数从0开始所以50-1
  TIM_TimeBaseStructure.TIM_Prescaler = 7199;  //预分频系数,为0时表示不分频 所以 7200-1 Time时钟为10K
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;   
  TIM_TimeBaseStructure.TIM_CounterMode =  TIM_CounterMode_Up;//计数模式
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  
  TIM_ARRPreloadConfig(TIM3, ENABLE);                                                                                                                                //自动重装允许
        
        TIM_ClearFlag(TIM3, TIM_FLAG_Update);                                                                                                                        //清除溢出中断
               
  TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE);       //允许定时器3中断
        //中断优先级NVIC设置
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


        TIM_Cmd(TIM3, ENABLE);  //使能TIMx        

/*******************************************************************************
* Function Name  : DMA1_Channel1_IRQHandler
* Description    : This function handles DMA1 Channel 1 interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DMA1_Channel1_IRQHandler(void)
{
        
   DMA1->IFCR = DMA1_IT_GL1;//清除通道全局中断标志

   //ADC_Oversampled_Data = Oversampling_GetConversion();        //得到过采样结果

   DMA1_Channel1->CCR &= 0xFFFFFFFE;//关闭DMA通道

   DMA1_Channel1->CNDTR = USART_REC_LEN;        //重新配置DMA 数目 地址

   DMA1_Channel1->CMAR = (u32)ADC_ConvertedValue;  

   ADC_DMA_STA=1;
        //处理得到数据

   TIM_Cmd(TIM3, DISABLE);                //关闭定时器



         
//   }


}

} [/mw_shl_code]

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

使用道具 举报

48

主题

177

帖子

0

精华

高级会员

Rank: 4

积分
782
金钱
782
注册时间
2013-4-23
在线时间
166 小时
发表于 2016-4-28 21:01:43 | 显示全部楼层
努力做,耐心等
回复

使用道具 举报

2

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-8-21
在线时间
13 小时
 楼主| 发表于 2016-4-28 22:16:16 | 显示全部楼层

谢谢帮顶请问有没有思路
回复

使用道具 举报

2

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-8-21
在线时间
13 小时
 楼主| 发表于 2016-4-29 13:38:31 | 显示全部楼层
ADC采集然后DMA传到数组里  这样会不会导致采集点数少啊
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-5-1 11:06:04 | 显示全部楼层
shibuguosan520 发表于 2016-4-29 13:38
ADC采集然后DMA传到数组里  这样会不会导致采集点数少啊

配置好是不会的。
论坛有参考,多搜索。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

2

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-8-21
在线时间
13 小时
 楼主| 发表于 2016-5-1 17:23:48 | 显示全部楼层
正点原子 发表于 2016-5-1 11:06
配置好是不会的。
论坛有参考,多搜索。

好的 谢谢原子哥
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-16 22:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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