stm32f103c8t6调试-while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET );卡死

最近使用stm32f103c8t6自带的ADC,遇到如下问题:while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET );
程序执行到这里跳不出循环

uint16_t myADC_GetValue(void)
{
	uint16_t value_ADC = 0;
	uint8_t i = 0;	 
	for(i=0;i<10;i++)
	{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换,这样ADC就可以进行转换了 conversion

		while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET );//规则组转换完成标志位,//12MHZ,  (1/12M)*(55.5+12.5)=5.6us,该循环大概等待5.6us			

		value_ADC += ADC_GetConversionValue(ADC1);
		
		
	}
	delay_ms(10);
	return value_ADC / 10;//获取ADC的转换值
}

详情:规则组ADC转换一直没完成。
我逛论坛发现2个解决方案:
(1)不使用标志位判断,用delay来假装转换结束。
原理:

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//把通道0写入在规则组菜单列表的第一个位置,采样时间是55.5个ADCCLK周期
	//12MHZ,  (1/12M)*(55.5+12.5)=5.6us

配置好参数后,采样时间大约是5.6us。那么用delay来延时一下,不管有没有把电压值转换完成,都继续执行,强制认为转换已经完成。
代码如下:

#include "ADC.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include "oled.h"
#include "delay.h"
void MyAdcTest_Config(void)//ADC初始化
{
	GPIO_InitTypeDef  myGPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);//打开ADC1的时钟
	

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC的时钟由主时钟6分频而来,即72/6=12MHZ
	
	
	myGPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	 
 	myGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 	//模拟输入,电压是模拟量(AIN模式是ADC的专属模式)
	myGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz

 	GPIO_Init(GPIOA, &myGPIO_InitStructure );	  //初始化GPIOD3,6
	//ADC_DeInit(ADC1);
	
	
	//ADC_StructInit(&ADC_InitStructure);
	
	

	
	
	 
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_None;//触发源:软件触发
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非连续转换
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描
	ADC_InitStructure.ADC_NbrOfChannel = 1;//通道数目,在非扫描模式下,通道数目可以不写

	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//把通道0写入在规则组菜单列表的第一个位置,采样时间是55.5个ADCCLK周期
	//12MHZ,  (1/12M)*(55.5+12.5)=5.6us
	
	ADC_Cmd(ADC1,ENABLE);//电源


	ADC_ResetCalibration(ADC1);//复位校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回复位校准的状态
	ADC_StartCalibration(ADC1);//开始校准
	while(ADC_GetCalibrationStatus(ADC1)==SET);//等待校准完成

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换,这样ADC就可以进行转换了 conversion

	
}

uint16_t myADC_GetValue(void)
{
	uint16_t value_ADC = 0;
	uint8_t i = 0;	 
	for(i=0;i<10;i++)
	{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换,这样ADC就可以进行转换了 conversion		
		delay_us(6);
		value_ADC += ADC_GetConversionValue(ADC1);
		
		
	}
	delay_ms(10);
	return value_ADC / 10;//获取ADC的转换值
}

(2)在初始化ADC时,ADC_Cmd(ADC1,DISABLE);
在获取ADC转换值的函数中ADC_Cmd(ADC1,ENABLE);
这里使用EOC标志位。原理我还没搞清楚。
代码如下:

#include "ADC.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include "oled.h"
#include "delay.h"
void MyAdcTest_Config(void)//ADC初始化
{
	GPIO_InitTypeDef  myGPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);//打开ADC1的时钟
	

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC的时钟由主时钟6分频而来,即72/6=12MHZ
	
	
	myGPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	 
 	myGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 	//模拟输入,电压是模拟量(AIN模式是ADC的专属模式)
	myGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz

 	GPIO_Init(GPIOA, &myGPIO_InitStructure );	  //初始化GPIOD3,6
	//ADC_DeInit(ADC1);
	
	
	//ADC_StructInit(&ADC_InitStructure);
	
	

	
	
	 
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_None;//触发源:软件触发
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非连续转换
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描
	ADC_InitStructure.ADC_NbrOfChannel = 1;//通道数目,在非扫描模式下,通道数目可以不写

	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//把通道0写入在规则组菜单列表的第一个位置,采样时间是55.5个ADCCLK周期
	//12MHZ,  (1/12M)*(55.5+12.5)=5.6us
	
	ADC_Cmd(ADC1,DISBLE);//电源


	ADC_ResetCalibration(ADC1);//复位校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回复位校准的状态
	ADC_StartCalibration(ADC1);//开始校准
	while(ADC_GetCalibrationStatus(ADC1)==SET);//等待校准完成

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换,这样ADC就可以进行转换了 conversion

	
}

uint16_t myADC_GetValue(void)
{
	uint16_t value_ADC = 0;
	uint8_t i = 0;	 
	for(i=0;i<10;i++)
	{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换,这样ADC就可以进行转换了 conversion
		ADC_Cmd(ADC1, ENABLE);
		while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET );//规则组转换完成标志位,//12MHZ,  (1/12M)*(55.5+12.5)=5.6us,该循环大概等待5.6us			
		value_ADC += ADC_GetConversionValue(ADC1);		
	}
	delay_ms(10);
	return value_ADC / 10;//获取ADC的转换值
}

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
stm32串口1和串口3数据互通,经测试同时发256字节不丢包 void usart3_init(u32 bound) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOBʱÖÓ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //´®¿Ú3ʱÖÓʹÄÜ USART_DeInit(USART3); //¸´Î»´®¿Ú3 //USART3_TX PB10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö GPIO_Init(GPIOB, &GPIO;_InitStructure); //³õʼ»¯PB10 //USART3_RX PB11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë GPIO_Init(GPIOB, &GPIO;_InitStructure); //³õʼ»¯PB11 USART_InitStructure.USART_BaudRate = bound;//²¨ÌØÂÊÒ»°ãÉèÖÃΪ9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //ÊÕ·¢Ä£Ê½ USART_Init(USART3, &USART;_InitStructure); //³õʼ»¯´®¿Ú 3 USART_Cmd(USART3, ENABLE); //ʹÄÜ´®¿Ú //ʹÄܽÓÊÕÖÐ¶Ï USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//¿ªÆôÖÐ¶Ï //ÉèÖÃÖжÏÓÅÏȼ¶ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//ÇÀÕ¼ÓÅÏȼ¶3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //×ÓÓÅÏȼ¶3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ NVIC_Init(&NVIC;_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷ TIM4_Int_Init(1000-1,7200-1); //10msÖÐ¶Ï USART3_RX_STA=0; //ÇåÁã TIM_Cmd(TIM4,DISABLE); //¹Ø±Õ¶¨Ê±Æ÷7 } //´®¿Ú3,printf º¯Êý //È·±£Ò»´Î·¢ËÍÊý¾Ý²»³¬¹ýUSART3_MAX_SEND_LEN×Ö½Ú void u3_printf(char* fmt,...) { u16 i,j; va_list ap; va_start(ap,fmt); vsprintf((char*)USART3_TX_BUF,fmt,ap); va_end(ap); i=strlen((const char*)USART3_TX_BUF); //´Ë´Î·¢ËÍÊý¾ÝµÄ³¤¶È for(j=0;j<i;j++) //Ñ­»··¢ËÍÊý¾Ý { while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï USART_SendData(USART3,USART3_TX_BUF[j]); } }
以下是一个简单的例子,展示了如何定义一个函数来读取STM32F103C8T6的内部ADC: ```c #include "stm32f10x.h" uint16_t adc_read(uint8_t channel) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能ADC外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 配置ADC引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 假设我们要读取ADC1的通道0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置ADC参数 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 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; ADC_Init(ADC1, &ADC_InitStructure); // 配置ADC通道 ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_71Cycles5); // 启动ADC转换 ADC_Cmd(ADC1, ENABLE); ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 等待转换完成 while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 读取转换结果 uint16_t result = ADC_GetConversionValue(ADC1); // 关闭ADC转换 ADC_Cmd(ADC1, DISABLE); return result; } ``` 在这个函数中,我们首先启用ADC外设时钟,并配置了ADC引脚。然后我们配置ADC参数,并指定要读取的通道。最后,我们启动ADC转换,并等待转换完成。一旦转换完成,我们读取转换结果并关闭ADC转换。请注意,这只是一个简单的例子,实际上你可能需要根据你的具体需求进行更多的配置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值