找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5274|回复: 1
打印 上一主题 下一主题
收起左侧

stm32定时器触发ADC采集DMA,只能进行一次转换,第二次就失败,咋原因啊?

[复制链接]
跳转到指定楼层
楼主
ID:267330 发表于 2019-1-11 14:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
只能进行一次DMA转换,第二次采集不行?

源码如下:
  1. #include "ADC.h"
  2. #include "usart.h"
  3. __IO uint16_t ADC_ConvertedValue[24];
  4. //************1.配置触发所用定时器参数************************
  5. /*******************************************************************************
  6. * 函数名+函数功能: My_trigger_Time_Init: LED初始化函数
  7. * 输入:usPer:自动重装载寄存器的值; usPsc:时钟预分频数
  8. 定时频率=72M/(usPer+1)=72/36000=2kHz;中断周期=usPsc*(1/定时频率)=1000*(1/2kHz)=0.5s
  9. * 输出: 无
  10. *******************************************************************************/
  11. void My_trigger_Time_Init(u16 usPer,u16 usPsc,u16 usPulse)
  12. {
  13. GPIO_InitTypeDef GPIO_InitTypeStruct;
  14. RCC_APB2PeriphClockCmd(trigger_Time_GPIO_CLK, ENABLE );
  15. GPIO_InitTypeStruct.GPIO_Pin    = trigger_Time_GPIO_PIN; //定时器1触发adc转换的输出的那个口
  16. GPIO_InitTypeStruct.GPIO_Speed  = GPIO_Speed_50MHz;
  17. GPIO_InitTypeStruct.GPIO_Mode   = GPIO_Mode_AF_PP;
  18. GPIO_Init(trigger_Time_GPIO_PORT, &GPIO_InitTypeStruct);

  19. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  20. TIM_OCInitTypeDef TIM_OCInitTypeStruct;
  21. //********************************1.初始化定时器参数********************************
  22. RCC_APB2PeriphClockCmd(trigger_Time_CLK,ENABLE);//本程序用的是TIME
  23. TIM_TimeBaseInitStructure.TIM_Period                   =usPer;            
  24. TIM_TimeBaseInitStructure.TIM_Prescaler                =usPsc;         
  25. TIM_TimeBaseInitStructure.TIM_ClockDivision            =TIM_CKD_DIV1;         
  26. TIM_TimeBaseInitStructure.TIM_CounterMode              =TIM_CounterMode_Up;//注意:必须配置成这个模式  
  27. TIM_TimeBaseInit(trigger_Time,&TIM_TimeBaseInitStructure);

  28. TIM_OCInitTypeStruct.TIM_OCMode       = TIM_OCMode_PWM1;         //注意:必须配置成pwm模式 ,不能更改
  29. TIM_OCInitTypeStruct.TIM_OutputState  = TIM_OutputState_Enable;
  30. TIM_OCInitTypeStruct.TIM_Pulse        = usPulse;
  31. TIM_OCInitTypeStruct.TIM_OCPolarity   = TIM_OCPolarity_Low;
  32. TIM_OC1Init(trigger_Time, &TIM_OCInitTypeStruct);  //【改】:用不同的定时器触发这个函数要改
  33. TIM_Cmd(trigger_Time,ENABLE);

  34.   TIM_InternalClockConfig(trigger_Time);
  35.   TIM_ARRPreloadConfig(trigger_Time, ENABLE);
  36. TIM_OC1PreloadConfig(trigger_Time,TIM_OCPreload_Enable);//【改】:用不同的定时器触发这个函数要改

  37. TIM_CtrlPWMOutputs(trigger_Time, ENABLE);      //这个是必须有的
  38.   
  39. }
  40. //************2.配置触发所用定时器参数************************
  41. /*******************************************************************************
  42. * 函数名+功能: My_ADC_Init:初始化函数
  43. * 输入 : 无
  44. * 输出 : 无
  45. *******************************************************************************/
  46. void My_DMA_Init(void)
  47. {
  48. DMA_InitTypeDef DMA_InitStructure;
  49. RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);
  50. DMA_DeInit(ADC_DMA_Channel);     
  51. DMA_InitStructure.DMA_PeripheralBaseAddr    = ( uint32_t ) ( & ( ADC_x->DR ) );//ADC的数据寄存器的地址
  52. DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)&ADC_ConvertedValue;//【改】:根据数据所放地址(16位)
  53. DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralSRC;
  54. DMA_InitStructure.DMA_BufferSize            = 24;      //【改】:
  55. DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;
  56. DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;   
  57. DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_HalfWord;
  58. DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_HalfWord;   //16位
  59. DMA_InitStructure.DMA_Mode                  = DMA_Mode_Normal;             //传送一次
  60. DMA_InitStructure.DMA_Priority              = DMA_Priority_High;
  61. DMA_InitStructure.DMA_M2M                   = DMA_M2M_Disable;
  62. DMA_Init(ADC_DMA_Channel, &DMA_InitStructure);
  63. DMA_Cmd(ADC_DMA_Channel , ENABLE);
  64. //*********************用中断下面就需要,不用DMA中断下面就不需要*************
  65.   DMA_ITConfig(ADC_DMA_Channel,DMA_IT_TC,ENABLE);
  66.   DMA_ClearFlag(DMA1_FLAG_TC1);
  67.   NVIC_InitTypeDef  NVIC_InitStructure;
  68.   NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn;            //改
  69.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  //改
  70.   NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;        //改
  71.   NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;         
  72.   NVIC_Init(&NVIC_InitStructure);
  73. }

  74. void My_ADC_Init( )
  75. {
  76.   My_DMA_Init( );
  77. //*******************初始化ADC--GPIO引脚***********************************************
  78. GPIO_InitTypeDef GPIO_InitStructure;
  79. RCC_APB2PeriphClockCmd( ADC_GPIO_CLK, ENABLE );
  80. GPIO_InitStructure.GPIO_Pin       =ADC_PIN;
  81. GPIO_InitStructure.GPIO_Mode      =GPIO_Mode_AIN; //这个必须为模拟输入。
  82. GPIO_Init(ADC_PORT, &GPIO_InitStructure);
  83. //*******************配置ADC初始化***********************************************
  84. ADC_InitTypeDef ADC_InitStruct;
  85. RCC_ADCCLKConfig(RCC_PCLK2_Div6);       //【改】:
  86. RCC_APB2PeriphClockCmd(ADC_CLK, ENABLE );  
  87. ADC_DeInit(ADC_x);  

  88. ADC_InitStruct.ADC_Mode                = ADC_Mode_Independent;     
  89. ADC_InitStruct.ADC_ScanConvMode        = DISABLE;         
  90. ADC_InitStruct.ADC_ContinuousConvMode  = DISABLE;    //注意:不要使用连续转换模式,否则只要出发一次,后续的转换就不会停止,,这样第一次以后的ADC,就不是有定时器触发了。
  91. ADC_InitStruct.ADC_ExternalTrigConv    = ADC_ExternalTrigConv_T1_CC1;//【改】:根据不同的定时器触发脚
  92. ADC_InitStruct.ADC_DataAlign           = ADC_DataAlign_Right;        
  93. ADC_InitStruct.ADC_NbrOfChannel        = 1;      
  94. ADC_Init(ADC_x, &ADC_InitStruct);

  95. ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL, 1, ADC_SampleTime_1Cycles5);
  96.   ADC_InjectedSequencerLengthConfig(ADC_x, 1);
  97.   
  98. ADC_ExternalTrigInjectedConvConfig(ADC_x, ADC_ExternalTrigConv_T1_CC1 );//??????ADC_ExternalTrigInjecConv_None

  99. ADC_AutoInjectedConvCmd(ADC_x, ENABLE);
  100. ADC_ExternalTrigConvCmd(ADC_x,ENABLE);   //ADC外部触发使能

  101. ADC_DMACmd(ADC_x, ENABLE);//使能ADC DMA 请求这句不能少。
  102. ADC_Cmd(ADC_x, ENABLE);               //是能ADC

  103. ADC_ResetCalibration(ADC_x);
  104.   while(ADC_GetResetCalibrationStatus(ADC_x));
  105.   ADC_StartCalibration(ADC_x);
  106.   while(ADC_GetCalibrationStatus(ADC_x));
  107.   
  108. }
  109. void DMA1_Channel1_IRQHandler(void)
  110. {   
  111. int kl=0;
  112.   if(DMA_GetITStatus(DMA1_IT_TC1))                  //转换完成
  113.   {                        
  114.   TIM_Cmd(TIM1, DISABLE);
  115.     DMA_Cmd(DMA1_Channel1, DISABLE);
  116.   for(kl=0;kl<24;kl++)
  117.   {
  118.    printf("\r\n The current AD value = %f V \r\n",(float) ADC_ConvertedValue[kl]/4096*3.3); //把电压值用显示
  119.    printf("\r\n\r\n");
  120.    }
  121. }
  122.   DMA_ClearFlag(DMA1_FLAG_TC1);

  123. }

复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:579380 发表于 2019-7-7 14:25 | 只看该作者
你的DMA模式(DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //传送一次)设置有误,改成连续传输应该就可以了。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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