OpenEdv-开源电子网

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

关于STM32F407的ADC+TIM+DMA采样

[复制链接]

1

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2017-8-25
在线时间
0 小时
发表于 2017-8-25 15:01:03 | 显示全部楼层 |阅读模式
4金钱
不知道哪里出问题了,初衷是用TIM3每500ms触发一次ADC1的通道5采样外部电压,再通过DMA传数据到内存,但是我调试时发现   ADC1的数据寄存器只更新的一次,现在问题就是用TIM只触发了一次ADC采样。 采用TIM+ADC+DMA是为了解放CPU,提高工作效率,没采样定时器中断。DMA工作的前提是外设有数据让它取,就是ADC数据寄存器ADC_DR中有值更新,但是我用Keil5调试时发现ADC_DR中的值只更新了一次,这代表TIM定时到后,只触发了一次ADC转换。
  //adc.h

  #ifndef __ADC__
  #define __ADC__
  #include "sys.h"

  void gpioled_config(void);
  void gpio_config(void);
  void adc_config(void);
  void tim_config(void);
  void dma_config(void);

#endif
*********************************************************************************************************

  //adc.c

  #include "stm32f4xx_conf.h"
  #include "sys.h"
  #include "stm32f4xx_spi.h"
  #include "delay.h"
  #include "stm32f4xx_adc.h"
  #include "stm32f4xx_dma.h"
  #include "stm32f4xx_dma2d.h"
  #include "adc.h"


  void gpioled_config(void)
  {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOF, &GPIO_InitStructure);
  }

    void gpio_config(void)
    {
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

      GPIO_InitTypeDef  GPIO_InitStructure;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    }

  void adc_config(void)
  {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //是否提高采样率
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //ADC独立模式
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; //配置成21M,保证ADC不超过36M
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //采样通道之间的间隔
ADC_CommonInit(&ADC_CommonInitStructure);

ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //ADC单次模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;  //TIM3外部触发
ADC_InitStructure.ADC_ExternalTrigConvEdge =ADC_ExternalTrigConvEdge_Rising;  //上升沿触发
ADC_InitStructure.ADC_NbrOfConversion = 1; //一个转换序列
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;  //采样精度为12位
ADC_InitStructure.ADC_ScanConvMode = DISABLE;  //扫描模式禁止
ADC_Init(ADC1,&ADC_InitStructure);

ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_480Cycles); //配置ADC转换通道

ADC_Cmd(ADC1,ENABLE); //使能ADC
ADC_DMACmd(ADC1,ENABLE); //使能ADC的DMA
}

void tim_config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV4;  //定时器时钟168M/4*2 = 84M
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_Period = 4999;  // 重载数
TIM_TimeBaseInitStructure.TIM_Prescaler = 8399;   //分频系数
//        TIM_TimeBaseInitStructure.TIM_RepetitionCounter   高级定时器才用到,不管
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);

TIM_ARRPreloadConfig(TIM3,ENABLE);

TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update); //定时器触发输出

TIM_Cmd(TIM3,ENABLE); // 使能定时器
}

void dma_config(void)
{
u16 adcbuffer[24];
u16 *a = adcbuffer;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);

DMA_DeInit(DMA1_Stream4);

DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_BufferSize = 128;
DMA_InitStructure.DMA_Channel= DMA_Channel_5;//DMA通道5
DMA_InitStructure.DMA_DIR= DMA_DIR_PeripheralToMemory;//传输方向为外设到内存
DMA_InitStructure.DMA_FIFOMode= DMA_FIFOMode_Disable;//DMA的FIFO模式禁止
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_Memory0BaseAddr = ((uint16_t)&adcbuffer); //内存地址
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //半字传输
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址递增
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //DMA循环模式开启
DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)&(ADC1->DR)); //外设地址
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//半字传输
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址递增
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级高
DMA_Init(DMA1_Stream4, &DMA_InitStructure);

DMA_Cmd(DMA1_Stream4,ENABLE);
}

*******************************************************************************************************************

//mian.c

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "adc.h"


int main(void)
{
uart_init(115200);
delay_init(168);
gpioled_config();
PFout(9) = 0;
PFout(10) = 0;
  gpio_config();
  adc_config();
dma_config();
  tim_config();

while(1)
{
   PFout(9) = 1;
   PFout(10) = 1;
   delay_ms(100);
PFout(9) = 0;
PFout(10) = 0;
   delay_ms(100);
}
}

**************************************************************************************************
以上就是我的程序了,是哪里没配,还是哪里没配对,请大家多多指教!!!
难道是我数据流配错了?或者我的TIM时钟频率或者是ADC的采样时间间隔有问题,它们之间搭配出现问题了,请各位不吝指教。


DMA1数据流

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

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2017-8-25
在线时间
0 小时
 楼主| 发表于 2017-8-25 15:01:51 | 显示全部楼层
   现在有2个想法在我脑子了,有点困惑哦。
     1.我这样写程序的初衷是为了靠TIM控制ADC采样,但不是用TIM的中断。例如我要一个周波内(20ms)采20个点,那配成每1.05ms,定时器计数溢出,触发一次单次ADC采样,从而达到目的。
    2. 如果ADC采样配成连续模式,TIM触发一次后ADC自己就一直在转换,采样的时间间隔 = ADC转换通道的转换时间+ADC通道之间的间隔,其实这个时间很快的,也达不到我要的目的。
   是不是要达到我这种目的不是这样配的。
回复

使用道具 举报

5

主题

103

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
453
金钱
453
注册时间
2016-8-8
在线时间
101 小时
发表于 2017-9-21 21:18:57 | 显示全部楼层
虽然你这个贴有点久了。刚好我也在弄这个,不过我是用F103。

我的想法是DMA传输完成中断,就是说DMA传输完128个中断。
但我还没弄到这里。

但我现在有个问题想请教
DMA_BufferSize = 128;
你这128个Buffer  变量是怎么定义的,我是直接定义的一个数组。
但我发现我采出来的ADC值是同一个数,电位器怎么调都不会变,但
不通过DMA却是正确的。

如果可以  可以跟我说说你是怎么处理DAM递增的问题的。
希望你能看到,谢谢!!
如何拿下蒙住眼的树叶。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-18 10:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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