STM32利用DMA方式采集多路ADC数值并周期传送

芯片使用的是STM32f103C8T6,编译器是Keil 5,使用的标准固件库3.5版本。

首先,配置时钟,配置NVIC就不说了。

开门见山,直接上代码吧:

1、配置ADC,DMA:

	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_5|GPIO_Pin_4;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	DMA_DeInit(DMA1_Channel1);
	DMA_InitStructure.DMA_PeripheralBaseAddr=(unsigned int)&(ADC1->DR);      
	DMA_InitStructure.DMA_MemoryBaseAddr=(unsigned int)ADC1_DMA1_Buffer;           
	DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;												
	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_Circular;								
	DMA_InitStructure.DMA_Priority=DMA_Priority_High;												
	DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;					
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);
	DMA_Cmd(DMA1_Channel1,ENABLE);
	
	ADC_DeInit(ADC1);
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;													
	ADC_InitStructure.ADC_ScanConvMode=ENABLE;															
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;												
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T3_TRGO;			
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;										
	ADC_InitStructure.ADC_NbrOfChannel=4;							
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_4,1,ADC_SampleTime_41Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_5,2,ADC_SampleTime_41Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_6,3,ADC_SampleTime_41Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_7,4,ADC_SampleTime_41Cycles5);

	
	ADC_DMACmd(ADC1,ENABLE);
	ADC_Cmd(ADC1,ENABLE);
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	ADC_ExternalTrigConvCmd(ADC1,ENABLE);

以上,配置ADC的同时,开启DMA传送的请求,也配置转换的DMA,注意转换的ADC模式,要选择独立模式,因为这里只涉及了单个ADC,不需要同步;连续采样模式,原理是完成一次采集后触发一次中断,接着继续进行下一次转换,不终止;开启扫描模式。触发方式采用ADC_ExternalTrigConv_T3_TRGO,是利用定时器3的周期中断触发DMA传输,这样实现周期传送数据。

2、配置TIM

这里采用TIM3:

	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
	
	TIM_TimeBaseStructure.TIM_Period=arr;
	TIM_TimeBaseStructure.TIM_Prescaler=psc;
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
	TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);

这里系统频率是HSI二分频后送入PLL,再通过PLL 16倍频到64MHz,所以,这里的TIM3的时钟频率为64MHz,在设置预分频系数的时候,将频率降低,分频后的数值,就是计数频率,也就是1S计数数值,再计算所要的周期数,即可填写重装载值。

例如:设置5ms的周期中断(1000/5=200Hz),预分频系数为3200时,分频后的计数频率为20000,也就是1s计2000个数,则重装值为20000/200=100。

再就是进入周期中断的时候要及时清中断标志位,防止下次进不去中断。
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

3、读取数据的时候直接读取DMA缓存ADC1_DMA1_Buffer的值就可以,这里的值时根据Rank的顺序依次转换的。

以上。

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值