标题:
stm32定时器触发ADC采集DMA,只能进行一次转换,第二次就失败,咋原因啊?
[打印本页]
作者:
jiangkeqin_sy
时间:
2019-1-11 14:11
标题:
stm32定时器触发ADC采集DMA,只能进行一次转换,第二次就失败,咋原因啊?
只能进行一次DMA转换,第二次采集不行?
源码如下:
#include "ADC.h"
#include "usart.h"
__IO uint16_t ADC_ConvertedValue[24];
//************1.配置触发所用定时器参数************************
/*******************************************************************************
* 函数名+函数功能: My_trigger_Time_Init: LED初始化函数
* 输入:usPer:自动重装载寄存器的值; usPsc:时钟预分频数
定时频率=72M/(usPer+1)=72/36000=2kHz;中断周期=usPsc*(1/定时频率)=1000*(1/2kHz)=0.5s
* 输出: 无
*******************************************************************************/
void My_trigger_Time_Init(u16 usPer,u16 usPsc,u16 usPulse)
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(trigger_Time_GPIO_CLK, ENABLE );
GPIO_InitTypeStruct.GPIO_Pin = trigger_Time_GPIO_PIN; //定时器1触发adc转换的输出的那个口
GPIO_InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(trigger_Time_GPIO_PORT, &GPIO_InitTypeStruct);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitTypeStruct;
//********************************1.初始化定时器参数********************************
RCC_APB2PeriphClockCmd(trigger_Time_CLK,ENABLE);//本程序用的是TIME
TIM_TimeBaseInitStructure.TIM_Period =usPer;
TIM_TimeBaseInitStructure.TIM_Prescaler =usPsc;
TIM_TimeBaseInitStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;//注意:必须配置成这个模式
TIM_TimeBaseInit(trigger_Time,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeStruct.TIM_OCMode = TIM_OCMode_PWM1; //注意:必须配置成pwm模式 ,不能更改
TIM_OCInitTypeStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitTypeStruct.TIM_Pulse = usPulse;
TIM_OCInitTypeStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(trigger_Time, &TIM_OCInitTypeStruct); //【改】:用不同的定时器触发这个函数要改
TIM_Cmd(trigger_Time,ENABLE);
TIM_InternalClockConfig(trigger_Time);
TIM_ARRPreloadConfig(trigger_Time, ENABLE);
TIM_OC1PreloadConfig(trigger_Time,TIM_OCPreload_Enable);//【改】:用不同的定时器触发这个函数要改
TIM_CtrlPWMOutputs(trigger_Time, ENABLE); //这个是必须有的
}
//************2.配置触发所用定时器参数************************
/*******************************************************************************
* 函数名+功能: My_ADC_Init:初始化函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void My_DMA_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);
DMA_DeInit(ADC_DMA_Channel);
DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADC_x->DR ) );//ADC的数据寄存器的地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;//【改】:根据数据所放地址(16位)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 24; //【改】:
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //传送一次
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(ADC_DMA_Channel, &DMA_InitStructure);
DMA_Cmd(ADC_DMA_Channel , ENABLE);
//*********************用中断下面就需要,不用DMA中断下面就不需要*************
DMA_ITConfig(ADC_DMA_Channel,DMA_IT_TC,ENABLE);
DMA_ClearFlag(DMA1_FLAG_TC1);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn; //改
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //改
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //改
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void My_ADC_Init( )
{
My_DMA_Init( );
//*******************初始化ADC--GPIO引脚***********************************************
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( ADC_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin =ADC_PIN;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN; //这个必须为模拟输入。
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
//*******************配置ADC初始化***********************************************
ADC_InitTypeDef ADC_InitStruct;
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //【改】:
RCC_APB2PeriphClockCmd(ADC_CLK, ENABLE );
ADC_DeInit(ADC_x);
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; //注意:不要使用连续转换模式,否则只要出发一次,后续的转换就不会停止,,这样第一次以后的ADC,就不是有定时器触发了。
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//【改】:根据不同的定时器触发脚
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC_x, &ADC_InitStruct);
ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL, 1, ADC_SampleTime_1Cycles5);
ADC_InjectedSequencerLengthConfig(ADC_x, 1);
ADC_ExternalTrigInjectedConvConfig(ADC_x, ADC_ExternalTrigConv_T1_CC1 );//??????ADC_ExternalTrigInjecConv_None
ADC_AutoInjectedConvCmd(ADC_x, ENABLE);
ADC_ExternalTrigConvCmd(ADC_x,ENABLE); //ADC外部触发使能
ADC_DMACmd(ADC_x, ENABLE);//使能ADC DMA 请求这句不能少。
ADC_Cmd(ADC_x, ENABLE); //是能ADC
ADC_ResetCalibration(ADC_x);
while(ADC_GetResetCalibrationStatus(ADC_x));
ADC_StartCalibration(ADC_x);
while(ADC_GetCalibrationStatus(ADC_x));
}
void DMA1_Channel1_IRQHandler(void)
{
int kl=0;
if(DMA_GetITStatus(DMA1_IT_TC1)) //转换完成
{
TIM_Cmd(TIM1, DISABLE);
DMA_Cmd(DMA1_Channel1, DISABLE);
for(kl=0;kl<24;kl++)
{
printf("\r\n The current AD value = %f V \r\n",(float) ADC_ConvertedValue[kl]/4096*3.3); //把电压值用显示
printf("\r\n\r\n");
}
}
DMA_ClearFlag(DMA1_FLAG_TC1);
}
复制代码
作者:
lihuawei6992
时间:
2019-7-7 14:25
你的DMA模式(DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //传送一次)设置有误,改成连续传输应该就可以了。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1