基于STM32F4的ADC实验

本文详细介绍了STM32新手如何配置ADC1的通道5进行单次转换,涉及时钟配置、HAL库回调函数理解、ADC初始化、通道配置及实际操作步骤。通过实例学习了HAL_ADC_MspDeInit的用法和ADC分频系数选择。
摘要由CSDN通过智能技术生成

备注:此实验是根据正点原子视频所写。初学STM32,完全是用于自我记录,若有问题,麻烦指正。

实验目的:ADC1的通道5(PA5)进行单次转换

1.开启PA口时钟和ADC1时钟,设置PA1为模拟输入。

这其中需要用到回调函数:void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)。进入定义去看,这是一个弱函数。笔者找到的答案在如下:关于HAL库中HAL_XX_Init 与HAL_XX_MspInit的问题https://blog.csdn.net/weixin_42717898/article/details/112346671?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-1-112346671.pc_agg_new_rank&utm_term=MspDeInit+MspInit+%E5%92%8C&spm=1000.2123.3001.4430

但还是没有理解何时使用HAL_PPP_MspDeInit函数。其具体代码如下:

//¿ªÆôPA¿ÚʱÖÓºÍADC1ʱÖÓ
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)  //»Øµ÷º¯Êý
{
	
	__HAL_RCC_GPIOA_CLK_ENABLE();  // ʹÄÜGPIOA
	__HAL_RCC_ADC1_CLK_ENABLE();   //ʹÄÜADC1
	
	GPIO_InitTypeDef GPIO_Initure;  //¶¨Òå½á¹¹Ìå 
	GPIO_Initure.Mode=GPIO_MODE_ANALOG;
	GPIO_Initure.Pin=GPIO_PIN_5;
	GPIO_Initure.Pull=GPIO_NOPULL;
	GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}

其中需要特别注意,此时GPIO_Initure.Mode=GPIO_MODE_ANALOG//模拟量,与此前做跑马灯的实验不同。

2.初始化ADC1,包括预分频系数等。

调用HAL_ADC_Init()函数。进入定义看, 有一个入口参数。则先定义一个结构体:ADC_HandleTypeDef adc_handler; 再进行参数初始化。又因为Init为结构体,再对其成员变量进行初始化。

ClockPrescaler:为分频系数,有2/4/6/8,F4不能超过36MHz。

ContinuousConvMode:开启连续转换模式或者单次转换模式。

DataAlign:数据对齐方式,左对齐或者右对齐。规则组可采用右对齐,不用移位,可直接读出。

DiscontinuousConvMode:不连续采样模式。

DMAContinuousRequests:开启DMA请求连续模式或者单独模式。

EOCSelection:是否开启EOC中断。

ExternalTrigConv:外部触发方式。

ExternalTrigConvEdge:外部触发边沿。

NbrOfConversion:规则序列中有多少个转换

NbrOfDiscConversion:不连续采样通道。

Resolution:分辨率,12/10/8/6位。位数越高,越精确。

ScanConvMode:扫描模式,对于多通道而言,此实验为单通道。

3.配置ADC通道序列。

需要用到HAL_ADC_ConfigChannel();函数。

HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)

从定义可知,有两个入口参数。第一个入口参数已经定义过,进入定义,看第二个入口参数:

typedef struct 
{
  uint32_t Channel;       
  uint32_t Rank;                                       
  uint32_t SamplingTime;                                
  uint32_t Offset;         
}ADC_ChannelConfTypeDef;

Channel:ADC通道。

Rank:规则通道中第几个转换。

SamplingTime:采样时间。

Offset:对于注入通道而言的,此实验为规则通道。

单通道的转换时间公式为:Tconv = Sampling time + 12.5 cycles。

4.开启ADC1。

HAL_ADC_Statt();。

5.等待转换完成。

HAL_ADC_PollForConversion();。

6.读取转换结果。

HAL_ADC_GetValue();。

7.其完整代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"

//1.¿ªÆôPA¿ÚʱÖÓºÍADC1ʱÖÓ
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)  //»Øµ÷º¯Êý
{
	
	__HAL_RCC_GPIOA_CLK_ENABLE();  // ʹÄÜGPIOA
	__HAL_RCC_ADC1_CLK_ENABLE();   //ʹÄÜADC1
	
	GPIO_InitTypeDef GPIO_Initure;  //¶¨Òå½á¹¹Ìå 
	GPIO_Initure.Mode=GPIO_MODE_ANALOG;
	GPIO_Initure.Pin=GPIO_PIN_5;
	GPIO_Initure.Pull=GPIO_NOPULL;
	GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}


//2.³õʼ»¯ADC1
ADC_HandleTypeDef adc_handler;  //¶¨Òå½á¹¹Ìå
void MY_ADC_Init(void)
{
	HAL_ADC_Init(&adc_handler); 
	//²ÎÊý³õʼ»¯
	adc_handler.Instance=ADC1;
	//InitΪ½á¹¹Ì壬¶ÔÆä³ÉÔ±±äÁ¿½øÐгõʼ»¯
	adc_handler.Init.ClockPrescaler= ADC_CLOCK_SYNC_PCLK_DIV4  ;//ʱÖÓ·ÖƵϵÊý,F4²»Äܳ¬¹ý36MHz
	adc_handler.Init.ContinuousConvMode= DISABLE;//Á¬Ðøת»»Ä£Ê½
	adc_handler.Init.DataAlign= ADC_DATAALIGN_RIGHT ;//Êý¾Ý¶ÔÆë·½·¨£¬¹æÔò×é²ÉÓÃÓÒ¶ÔÆë
	adc_handler.Init.DiscontinuousConvMode = DISABLE ;//²»Á¬Ðøת»»Ä£Ê½ 
	adc_handler.Init.DMAContinuousRequests=DISABLE;
	adc_handler.Init.EOCSelection=DISABLE;//ÊÇ·ñ¿ªÆôEOCÖжÏ
	adc_handler.Init.ExternalTrigConv= ADC_SOFTWARE_START ;//Íⲿ´¥·¢·½Ê½ £¬´Ë´¦Ê¹ÓÃÈí¼þ´¥·¢·½Ê½  
	adc_handler.Init.ExternalTrigConvEdge= DISABLE ;//Íⲿ´¥·¢±ßÑØ
	adc_handler.Init.NbrOfConversion= 1 ;//¹æÔòÐòÁÐת»»£¬Ö»ÐèÒª¶ÔPA5½øÐÐת»»
	adc_handler.Init.NbrOfDiscConversion=0;
	adc_handler.Init.Resolution= ADC_RESOLUTION_12B ;//·Ö±æÂÊ
	adc_handler.Init.ScanConvMode=  DISABLE;//ɨÃèģʽ£¬¶ÔÓÚ¶àͨµÀ¶øÑÔ£¬´Ë´¦Îªµ¥Í¨µÀ
}


//ÅäÖùæÔòͨµÀ£¬²¢»ñȡת»»½á¹û
u16 Get_Adc(u32 ch)
{
	ADC_ChannelConfTypeDef channelConfig;//¶¨Òå½á¹¹Ìå
	//½á¹¹Ìå±äÁ¿½øÐгõʼ»¯ 
	channelConfig.Channel= ch;//ͨµÀ
	channelConfig.Offset=  0; //Offset¶Ô×¢ÈëͨµÀ¶øÑÔ£¬´ËʵÑéΪ¹æÔòͨµÀ 
	channelConfig.Rank= 1;    //ÐòÁкţ¬´ËʵÑéΪµ¥´Îת»»£¬ÉèÖÃΪ1
	channelConfig.SamplingTime= ADC_SAMPLETIME_480CYCLES ;  //ÉèÖòÉÑùʱ¼ä  
	
	HAL_ADC_ConfigChannel(&adc_handler,&channelConfig);
	
	
	//¿ªÆôADC
	HAL_ADC_Start(&adc_handler);
	//µÈ´ýת»»
	HAL_ADC_PollForConversion(&adc_handler,10);
	//»ñÈ¡½á¹û
	 return HAL_ADC_GetValue(&adc_handler);
}

//ȡƽ¾ùÖµ
u16 Get_Adc_Average(u32 ch,u8 times)
{	
	u32 temp_val = 0;
	u8 t;
	for(t=0;t<times;t++){
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
	
}

int main(void)
{
    u16 adcx;
	float temp;
    HAL_Init();                     //???HAL?   
    Stm32_Clock_Init(360,25,2,8);   //????,180Mhz
    delay_init(180);                //???????
    uart_init(115200);              //???USART
    LED_Init();                     //???LED 
    KEY_Init();                     //?????
    SDRAM_Init();                   //???SDRAM
    LCD_Init();                     //???LCD
    MY_ADC_Init();                  //???ADC1??5
    
	POINT_COLOR=RED; 
	LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7");	
	LCD_ShowString(30,70,200,16,16,"ADC TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2016/1/13");	  
	POINT_COLOR=BLUE;//???????
	LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");	      
	LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");	//???????????  	
    while(1)
	{
        adcx=Get_Adc_Average(ADC_CHANNEL_5,20);//????5????,20????
		LCD_ShowxNum(134,130,adcx,4,16,0);    //??ADCC???????
		temp=(float)adcx*(3.3/4096);          //???????????????,??3.1111
		adcx=temp;                            //???????adcx??,??adcx?u16??
		LCD_ShowxNum(134,150,adcx,1,16,0);    //??????????,3.1111??,??????3
		temp-=adcx;                           //????????????,??????,??3.1111-3=0.1111
		temp*=1000;                           //??????1000,??:0.1111????111.1,??????????
		LCD_ShowxNum(150,150,temp,3,16,0X80); //??????(??????????),???????111.
		LED0=!LED0;
		delay_ms(250);	
	}  
}

8.提出问题。

a.HAL_XXX_MspDeInit函数的用法。

b.ADC的分频系数。

c.采样时间选哪个最好,为什么。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值