这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 关于STM32F103VET6 ADC_FLAG_EOC标志位的一些拙见

共3条 1/1 1 跳转至

关于STM32F103VET6 ADC_FLAG_EOC标志位的一些拙见

助工
2015-04-24 11:14:04     打赏

今天在学习adc库函数   于是图方便想整个不用序列通道的 多路采集来实验下效果

初始化部分代码如下

GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	/* 使能ADC1和GPIOC的时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
	
		/*配置ADC时钟,为PCLK2的8分频,即9MHz*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	/* 配置PC0,1,2,3为模拟输入模式 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    //设置GPIO为模拟输入
	GPIO_Init(GPIOC, &GPIO_InitStructure);				// 输入时不用设置速率
	
	ADC_DeInit(ADC1);     //复位ADC1将外设ADC1的全部寄存器重设为缺省值
	/* ADC1 初始化*/	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;			//独立ADC模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 	 				//禁止扫描模式,扫描模式用于多通道采集
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;			//单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//不使用外部触发转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 	//采集数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	 								//要转换的通道数目1
	ADC_Init(ADC1, &ADC_InitStructure);
	

	/* DISABLE ADC1 DMA */
	ADC_DMACmd(ADC1, DISABLE);    //关闭DMA请求 (不需要用到)
	
	/* 使能 ADC1 */
	ADC_Cmd(ADC1, ENABLE);
	
	/*复位校准寄存器 */   
	ADC_ResetCalibration(ADC1);
	/*等待校准寄存器复位完成 */
	while(ADC_GetResetCalibrationStatus(ADC1));
	
	/* ADC校准 */
	ADC_StartCalibration(ADC1);
	/* 等待校准完成*/
	while(ADC_GetCalibrationStatus(ADC1));
	
	/*开启ADC1的软件启动功能 */ 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);


读值的子程序

uint16_t Get_Adc(uint8_t ch) 
{
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,转换时间239.5个周期

ADC_SoftwareStartConvCmd(ADC1, ENABLE);	 //使能ADC1的转换功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//判断ADC转换结束标志位 等待转换结束
return ADC_GetConversionValue(ADC1);	//返回最近一次ADC的数据
}

 

那么问题来了    我使用PC0一个通道的时候  程序运行很好

然后在主程序跑3个通道的时候 就出现了问题

原本的接线是 PC 0,1,2分别接的是 电位器的中间     3.3V    GND  但是程序上把数据的位置混了

于是我开始检查 到底是哪出了问题


while (1)
	{
		CH0 =(float) Get_Adc(ADC_Channel_10)/4096*3.3; // 读取PC0转换的AD值
		DisplayFloat(CH0,21,6);	
		
		CH1 =(float) Get_Adc(ADC_Channel_11)/4096*3.3; // 读取PC1转换的AD值
		DisplayFloat(CH1,37,6);

		CH2 =(float) Get_Adc(ADC_Channel_12)/4096*3.3; // 读取PC2转换的AD值
		DisplayFloat(CH2,53,6);

		Delay(0x18ffee);  
	}

初始化部分是库函数  一般不会有错误   于是我去检查获取ADC值的子程序

有人说是没清除标志位 于是我加入了

ADC_ClearFlag(ADC1, ADC_FLAG_EOC);      // 清除转换结束标志位

然后结果还是这样 突然想起以前写外部adc的时候  读值都是直接加个延时  时间远大于转换周期

于是我在判断转换完成标志之后  加了一个1MS的延时


uint16_t Get_Adc(uint8_t ch)   
{
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,转换时间239.5个周期 提高转换       
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能ADC1的转换功能
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//判断ADC转换结束标志位 等待转换结束
	DelayMs(1);                         //延时1Ms等待外设ADC把数据写入ADC1_DR
	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC的数据
	
}

然后程序就正常了


由此不经想问在库函数的介绍中

ADC_FLAG_EOC不是转换完成的标志么   为什么判断标志完成后读值     数据会乱呢

唯一能理解的就是说  ADC转换完成  标志就被置位了

但是数据还没到ADC1_DR里面,于是需要人为添加一个短延时让ADC外设把数据移到DR里面。

不知道我说的对不对   不过问题是这样解决的。。。仅供参考,大神莫见笑





关键词: STM32 ADC    

院士
2015-04-25 10:06:39     打赏
2楼
添加硬件延时还是非常有必要的

助工
2015-05-22 16:14:34     打赏
3楼

找到原因了   把ADC初始化中

/*复位校准寄存器 */   
	ADC_ResetCalibration(ADC1);
	/*等待校准寄存器复位完成 */
	while(ADC_GetResetCalibrationStatus(ADC1));
	
	/* ADC校准 */
	ADC_StartCalibration(ADC1);
	/* 等待校准完成*/
	while(ADC_GetCalibrationStatus(ADC1));
	
	/*开启ADC1的软件启动功能 */ 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
最后一句    

/*开启ADC1的软件启动功能 */ 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
删除    就可以了正常使用了

虽然我也不知道为啥。。。


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]