stm32定时器触发ADC1多通道规则转换

stm32定时器触发ADC多通道规则转换

之前也查了不少资料,参考了其他人写的,综合了一下,通过定时器触发ADC多通道转换,并通过DMA传输数据,希望能给大家带来一些启发。
使用定时器2的CC2触发ADC1转换,AD转换包含ADC_Channel_8和ADC_Channel_9,转换结果通过DMA1_Channel1放入缓冲区

ADC为一个整体,其外部不单只外部引脚,除ADC外的其他所有均为外部
以下代码运行中stm32F103上,主时钟为72MHz

uint16_t AD_Data[200];		//AD转换结果存放
void  ADC_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1, ENABLE );	  //开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);		
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //ADC时钟6分频,12MHZ,ADC时钟最高不超过14MHz
	
	//ADC端口配置   PB0为ch8,PB1为ch9                   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;			//模拟输入状态
	GPIO_Init(GPIOB, &GPIO_InitStructure);					//初始化端口
	
/************ADC1初始化*************/
	ADC_DeInit(ADC1);  //复位ADC1相关寄存器

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//独立转换模式,单独使用ADC1
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;		//开启扫描模式,采集端口数量超过1个时,需开启扫描模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//关闭连续转换模式,连续转换开启后不需要其他触发就会一直转换,本例程为外部触发,需要关闭
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;	//外部触发源为TIM2的CC2
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;					//转换结果数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 2;									//需要转换的通道数为2个
	ADC_Init(ADC1, &ADC_InitStructure);										//初始化ADC1   
	/*设定两个通道的转换顺序和AD转换周期,通道8第一个转换,通道9第二个转换,注意转换顺序要连续,从1开始*/
	ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_239Cycles5);//
	ADC_RegularChannelConfig(ADC1,ADC_Channel_9,2,ADC_SampleTime_239Cycles5);
	
	/**********DMA传输配置*****************/
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR);		//外设地址为ADC1的数据寄存器
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Data[0];			//缓冲区地址为数据起始地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;					//数据由外设传输到缓冲区
	DMA_InitStructure.DMA_BufferSize = 200;								//DMA缓冲区大小,不能超过数组大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  	//外设地址不增长
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  			//内存地址增长
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //传输数据为16位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	//传输数据为16位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;						//DMA存储为循环模式,存储满之后会开始覆盖以往数据
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;				//DMA优先级
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;						//关闭内存到内存模式
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);							//初始化,ADC转换对应DMA通道1,不能修改

	/******开启DMA中断,优先级需要根据优先级分组选择,例程中采用的优先级分组2******/
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;  	//DMA1通道中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  	//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  		//从优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 			//开启
	NVIC_Init(&NVIC_InitStructure);  							//初始化
	DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE);				//开启DMA1通道1的传输完成中断
	
	ADC_DMACmd(ADC1,ENABLE);					//开启ADC与DMA的关联
	ADC_Cmd(ADC1, ENABLE);						//开启ADC1
	ADC_ResetCalibration(ADC1);					//重置ADC校准
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待重置完成
	ADC_StartCalibration(ADC1);	 				//开始校准
	while(ADC_GetCalibrationStatus(ADC1));	 	//等待校准完成			
	DMA_Cmd(DMA1_Channel1,ENABLE);				//开启DMA,
	ADC_ExternalTrigConvCmd(ADC1,ENABLE);		//开启外部触发
}	
/*DMA中断函数*/
void DMA1_Channel1_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)			//传输完成中断检测
	{
		DMA_ClearITPendingBit(DMA1_IT_TC1);
		//内容自行编写
	}
}

以上为ADC与DMA的初始化过程。

定时器2触发需使用PWM模式,定时器比较匹配输出信号,该信号用于触发AD转换。
触发信号未与外部引脚相连,所以引脚上不会产生PWM波形,与常规PWM波形发生只差引脚关联。

/*
	Period为PWM周期,Prescaler为定时器预分频洗漱
	定时器2采用内部时钟,为72MHz
*/
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
void TIM2_Init(u16 Period,u16 Prescaler)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);			
	
	TIM_TimeBaseStructure.TIM_Prescaler = Prescaler-1;				//预分频系数
	TIM_TimeBaseStructure.TIM_Period = Period-1;					//周期
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数模式,
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;			//定时器时钟不分频,为72MHz
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);					//初始化

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//PWM1模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse = Period/2;						//比较寄存器值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;		//比较匹配完成后输出极性
	TIM_OC2Init(TIM2, & TIM_OCInitStructure);						//初始化
	
	TIM_Cmd(TIM2,ENABLE);											//定时器使能
	TIM_InternalClockConfig(TIM2);									//定时内部时钟使能
	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);				//重装载使能
	TIM_UpdateDisableConfig(TIM2, DISABLE);
}

使用外部触发AD转换并采用DMA传输数据,比较适合需要高频率AD转换的环境,不用频繁手动开启AD转换,只需转换完成之后到DMA缓冲区读取即可。

你可能感兴趣的:(stm32分享,stm32,嵌入式,单片机,dma)