你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

定时器触发4路ADC采样,并使用DMA传输 求找问题

[复制链接]
汪文龙 提问时间:2015-5-14 12:34 /
本帖最后由 汪文龙 于 2015-5-14 12:50 编辑

想使用ADC进行4路采样,并将采样值由DMA存储在一个数组中。因为采样时间有将近1分钟,如果让ADC不停地采样,最终获得的数据量大的不行。所以决定用定时器触发ADC的方式,每0.5秒采样一次,1分钟的话,采样120次,共480个数据。
但是配置良久,ADC一直不工作,我真不知道怎么办了,所以在此求助大神。


请大家看看我下面的程序有什么问题,并给一点建议。




再者,小弟有几个问题,望前辈解惑。
1.多路ADC   是不是ADC每完成一路的转换,DMA就帮忙传送一次。
2.DMA_BufferSize ,好多地方都说这个是DMA缓冲大小,请问下这个有什么用,我的是四路ADC,所以我这里设置的是4,不知道是不是对的。




ADC+DMA程序段


#include "adc.h"
#include "led.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"
#include "stm32f4xx_gpio.h"

#define ADC3_DR_ADDRESS     ((uint32_t)0x4001224C)
extern int uhADC3ConvertedValue[504];

//------------------------------------------------------------------------------
//ADC3+DMA配置
//------------------------------------------------------------------------------
void ADC3_CH13_DMA_Config(void)
{
ADC_InitTypeDef        ADC_InitStructure;
ADC_CommonInitTypeDef  ADC_CommonInitStructure;
DMA_InitTypeDef       DMA_InitStructure;
GPIO_InitTypeDef      GPIO_InitStructure;
NVIC_InitTypeDef   NVIC_InitStructure;

//打开ADC3,DMA2,GPIO时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

//配置DMA
DMA_DeInit(DMA2_Stream0);

DMA_InitStructure.DMA_Channel = DMA_Channel_2;  
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)uhADC3ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 4;
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;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;   

DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);

//初始化采样端口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_5 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
  


//配置ADC
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T5_CC1;           //设置为TIM5_CC1触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC3, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 4, ADC_SampleTime_3Cycles);

ADC_DMACmd(ADC3, ENABLE);
ADC_Cmd(ADC3, ENABLE);

ADC_ITConfig(ADC3,ADC_IT_EOC,ENABLE);

NVIC_InitStructure.NVIC_IRQChannel  =ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority   = 0;   //从优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd   = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

void ADC_IRQHangler(void)         //程序调试
{
if(ADC_GetITStatus(ADC3,ADC_FLAG_EOC)==SET) //溢出中断
{
  if(IS_LED2_ON==1)
  {
   LED2_OFF;
  }
  else
  {
   LED2_ON;
  }
}
ADC_ClearITPendingBit(ADC3,ADC_FLAG_EOC);  //清除中断标志位

}



定时器TIM5程序段


#include "timer3.h"
#include "led.h"
#include "stm32f4xx_tim.h"


void TIM5_Int_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

TIM_TimeBaseInitStructure.TIM_Period=4200-1;
TIM_TimeBaseInitStructure.TIM_Prescaler=10000-1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Down;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);
  
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=0x7F;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

TIM_OC1Init(TIM5,&TIM_OCInitStructure);
TIM_Cmd(TIM5,ENABLE);
TIM_ITConfig(TIM5,TIM_IT_CC1,ENABLE);
TIM_CtrlPWMOutputs(TIM5, ENABLE);


}


main函数:
int main(void)
{

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
GPIO_Switch_Init();
LED_Init();

TIM3_Int_Init();


LCD_Init();           //LCD初始化
LCD_LayerInit();        //LCD层次显示初始化  
  
LTDC_Cmd(ENABLE);        //打开LTDC
  
LCD_GUIDisplay();

TIM2_Int_Init();

ADC3_CH13_DMA_Config();    //配置ADC3
TIM5_Int_Init();


while(1)
{   

}
}




收藏 评论14 发布时间:2015-5-14 12:34

举报

14个回答
二宽 回答时间:2015-5-14 12:45:00
玩得真高端,  还没玩会串口的飘过
拼命三郎 回答时间:2015-5-14 13:32:55
ddddd.png
拼命三郎 回答时间:2015-5-14 13:33:47
我的帖子里有一篇讲AD的,纯属个人见解。
Winddddd 回答时间:2015-5-14 13:45:51
没有选择ADC的时钟,RCC_ADCCLKConfig();
没有开启ADC转换,ADC_StartConversion();
汪文龙 回答时间:2015-5-14 15:05:35
Winddddd 发表于 2015-5-14 13:45
没有选择ADC的时钟,RCC_ADCCLKConfig();
没有开启ADC转换,ADC_StartConversion();

您好,我上面有使能ADC时钟呀
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
下面这句应该就是启动啊ADC的吧。
ADC_Cmd(ADC3, ENABLE);

朋友你说的两个函数我的库里面貌似都没有,我用的是STM32F428ZI的芯片
汪文龙 回答时间:2015-5-14 15:06:58
废鱼 回答时间:2015-5-14 15:38:22
DMA可以,设置为采集4路的倍数,比如采集十次,就改为40,数组定义不能小于40.
DMA缓冲区满了以后会触发一次中断,这个时候处理就可以了。
Winddddd 回答时间:2015-5-14 15:49:35
汪文龙 发表于 2015-5-14 15:05
您好,我上面有使能ADC时钟呀
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
下面这句应该就是 ...

库不一样吧,仔细看下你的库,最好能有库函数说明用户手册,看是不是漏掉了什么
bldc小菜鸟 回答时间:2015-5-14 16:01:44
你的adc是独立模式,要想用定时器触发采样,应该设置成注入模式,此外中断源为定时器中断,属于内部中断。
为什么是EEFOCUS小白 回答时间:2015-5-14 17:23:52
不懂帮顶
汪文龙 回答时间:2015-5-14 20:37:02
Winddddd 发表于 2015-5-14 15:49
库不一样吧,仔细看下你的库,最好能有库函数说明用户手册,看是不是漏掉了什么 ...

好的,谢谢哈!
yceast 回答时间:2015-11-12 17:26:41
有da的吗
wz002 回答时间:2015-12-11 16:39:58
我的定时器配置完成后比你多一句
TIM_ARRPreloadConfig(TIM1, ENABLE);

TIM_OC1PreloadConfig (TIM1, TIM_OCPreload_Enable);
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);

DMA_BufferSize是指DMA的缓冲区大小,既然你开辟了内存大小int uhADC3ConvertedValue[504];DMA_BufferSize就可以设置为504
my90dm 回答时间:2015-12-29 08:51:10
楼主,你好,我最近也在弄定时器触发ADC+DMA传输,请问程序调好了么?能否发我一份,谢谢!duanmincqu@163.com

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版