028 - STM32学习笔记 - ADC(二) 独立模式单通道中断采集

028 - STM32学习笔记 - 结构体学习(二)

在这里插入图片描述

上节对ADC基础知识进行了学习,这节在了解一下ADC相关的结构体。

一、ADC初始化结构体

在标准库函数中基本上对于外设都有一个初始化结构体xx_InitTypeDef(其中xx为外设名,例如之前使用过的GPIO_InitTypeDef),结构体成员用来设置外设的工作模式,通过标准库函数xx_Init()调用将这些设定的参数送入外摄对应的寄存器。

对于ADC来说也是这样的操作,先看一下ADC_InitTypeDef结构体的定义:

ADC_InitTypeDef结构体

typedef struct {
    uint32_t ADC_Resolution; 					//设置ADC分辨率选择
    FunctionalState ADC_ScanConvMode; 			 //设置ADC扫描选择
    FunctionalState ADC_ContinuousConvMode; 	 //设置ADC连续转换模式选择
    uint32_t ADC_ExternalTrigConvEdge; 			//设置ADC外部触发极性
    uint32_t ADC_ExternalTrigConv; 			    //设置ADC外部触发选择
    uint32_t ADC_DataAlign; 				   //设置输出数据对齐方式
    uint8_t ADC_NbrOfChannel; 				   //设置转换通道数目
} ADC_InitTypeDef;

ADC_Resolution:用于配置ADC的分辨率,可选的分辨率有12 位、10 位、8 位和 6 位。分辨率越高, AD转换数据精度越高,转换时间也越长;分辨率越低,AD转换数据精度越低,转换时间也越短。

ADC_Resolution_12b				//12位精度
ADC_Resolution_10b				//10位精度
ADC_Resolution_8b				//8位精度c
ADC_Resolution_6b				//6位精度

ADC_ScanConvMode:该成员主要用于配置ADC是否使用扫描,可选参数为ENABLE和DISABLE,如果只用到一个通道,配置为DISABLE,如果时多个通道,则选择ENABLE。

ADC_ContinuousConvMode:用于配置启动自动连续转换还是单次转换,可选参数为ENABLE(连续转换)和DISABLE(单次转换)。如果选择为单次转换,那么每次转换完成后,都需要手动控制才能重新启动转换。

ADC_ExternalTrigConvEdge:设置外部触发极性,如果使用外部触发,可选有:

ADC_ExternalTrigConvEdge_None				//禁止触发检测
ADC_ExternalTrigConvEdge_Rising				//上升沿触发检测
ADC_ExternalTrigConvEdge_Falling			//下降沿触发检测
ADC_ExternalTrigConvEdge_RisingFalling		//上升下降沿均检测

ADC_ExternalTrigConv:外部触发模式选择,可选的触发条件如下图-4,常用的一般使用软件自动触发:

在这里插入图片描述

ADC_DataAlign:设置转换结果数据对其模式,可选有右对齐ADC_DataAlign_Right或者左对齐ADC_DataAlign_Left,这里我们选择右对齐。

ADC_NbrOfChannel:设置AD转换通道数目。

ADC_CommonInitTypeDef结构体

除了ADC_InitTypeDef初始化结构体外,还有ADC_CommonInitTypeDef通用初始化结构,ADC_CommonInitTypeDef结构体内容决定了三个ADC共用的工作环境。

typedef struct{
  uint32_t ADC_Mode; 						//ADC模式选择
  uint32_t ADC_Prescaler; 					//ADC分频系数
  uint32_t ADC_DMAAccessMode;				//DMA模式配置
  uint32_t ADC_TwoSamplingDelay;			//采样延迟
}ADC_CommonInitTypeDef;

ADC_Mode:ADC工作模式选择在前面有学习过,有独立模式、双重模式以及三重模式;

ADC_Prescaler:ADC时钟分频系数选择,ADC时钟是由PCLK2分频而来,分频系数决定ADC时钟频率,可选的分频系数位2、4、6和8,在之前也学习过ADC的最大时钟配置为36MHz。

ADC_DMAAccessMode:DMA模式设置,在双重或者三重模式下才需要设置,可以设置三种模式,分别为:

ADC_DMAAccessMode_Disabled				//独立模式下选择
ADC_DMAAccessMode_1					    //模式1
ADC_DMAAccessMode_2					    //模式2
ADC_DMAAccessMode_3					    //模式3

ADC_TwoSamplingDelay:2个采样阶段之前的延迟,仅适用于双重或三重交错模式。

二、独立模式单通道采集实验

在F429实验板上,提供了一个板载贴片滑动变阻器,供我们调试ADC时使用,原理图如下:

在这里插入图片描述

滑动变阻器动触点连接到STM32的ADC通道引脚(GPIOC_3),固定触点一边接0V,一边接3.3V,因此旋转滑动变阻器调节旋钮时,动触点的电压会在0~3.3V之间变化。

根据以上电路设计,设计个模拟量采集程序,具体需要实现如下步骤:

  1. 初始化配置ADC目标引脚为模拟输入模式;
  2. 使能ADC时钟(再次强调,使用外设一定要先开启时钟!!!);
  3. 配置通用ADC为独立模式,采样4分频;
  4. 设置目标ADC为12位分辨率,1通道的连续转换,不需要外部触发;
  5. 设置ADC转换通道顺序及采样时间;
  6. 配置使能ADC转换完成中断,在中断内读取转换完数据;
  7. 启动ADC转换;
  8. 使能软件触发ADC转换。

这里需要注意,没用使用到DMA进行数据传输,而是使用中断方式进行读取。

bsp_adc.h

#ifndef __BSP_ADC_H_
#define __BSP_ADC_H_

#include "stm32f4xx.h"

#define R_ADC_IRQ               ADC_IRQn
#define R_ADC_INT_FUNCTION      ADC_IRQHandler
#define R_ADC_GPIO_PORT         GPIOC
#define R_ADC_GPIO_PIN          GPIO_Pin_3
#define R_ADC_GPIO_CLK          RCC_AHB1Periph_GPIOC

#define R_ADC                   ADC1
#define R_ADC_CLK               RCC_APB2Periph_ADC1
#define R_ADC_CHANNEL           ADC_Channel_13

void R_ADC_Init(void);
#endif

bsp_adc.c

#include "bsp_adc.h"

/** @brief  初始化ADC GPIO引脚
  * @parm   无
  * @retval 无
  */
static void R_ADC_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(R_ADC_GPIO_CLK,ENABLE);          //开启ADC外设引脚时钟
    GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN;           //配置引脚位3引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;           //配置引脚为模拟输入
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        //配置为无上下拉
    GPIO_Init(R_ADC_GPIO_PORT,&GPIO_InitStructure);         //初始化引脚
}

/** @brief  配置ADC引脚工作模式
  * @parm   无
  * @retval 无
  */
static void R_ADC_Mode_Config(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    RCC_APB2PeriphClockCmd(R_ADC_CLK,ENABLE);
    //-----------------ADC Common结构体参数初始化--------------//
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;        //设置模式为独立模式
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;     //设置为4分频
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;     //禁止DMA直接访问模式
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;       //设置采样间隔周期为10个周期
    ADC_CommonInit(&ADC_CommonInitStructure);
    //-----------------ADC Init结构体参数初始化--------------//
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;      //设置ADC采样分辨率为12位
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;               //多通道下才会用到扫描模式,这里直接禁止
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;          //设置为连续转换
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;     //禁用外部边沿触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;      //设置为右对齐
    ADC_InitStructure.ADC_NbrOfConversion = 1;                  //转换通道只有1个
    ADC_Init(R_ADC,&ADC_InitStructure);
    ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL,1,ADC_SampleTime_56Cycles);   //配置ADC通道转换顺序为1,第一个转换,才压根时间为56个时钟周期
    ADC_ITConfig(R_ADC,ADC_IT_EOC,ENABLE);      //ADC转换结束产生中断,在中断服务程序中读取转换数值
    ADC_Cmd(R_ADC,ENABLE);                  //使能ADC
    ADC_SoftwareStartConv(R_ADC);           //开始ADC转换,由软件触发
}

static void R_ADC_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);				//设置中断向量组为1
    NVIC_InitStructure.NVIC_IRQChannel = R_ADC_IRQ;				//配置中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	 //设置主优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//设置此优先级为1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//通道使能
    NVIC_Init(&NVIC_InitStructure);							   //初始化中断
}
void R_ADC_Init(void)
{
    R_ADC_GPIO_Config();
    R_ADC_Mode_Config();
    R_ADC_NVIC_Config();
}

main.c

#include "stm32f4xx.h"
#include "bsp_usart_dma.h"
#include "bsp_systick.h"
#include "bsp_adc.h"
#include <stdio.h>
__IO uint16_t ADC_Value;
float ADC_Vol = 0;
int main(void)
{
    DEBUG_USART1_Config();
    R_ADC_Init();
    SysTick_Init();
    printf("\r\n---------------ADC实验(中断模式)----------------\r\n");
    while(1)
    {
        Delay_ms(1000);
        printf("\r\n ADC数据(未转换) = 0x%04X \r\n",ADC_Value);
        
        ADC_Vol =(float)(ADC_Value*3.3/4096); // 读取转换的 AD 值 
        printf("\r\n ADC数据(已转换) = %.2f V \r\n",ADC_Vol);
    }
}

stm32f4xx_it.c

//此处记得在头文件中声明函数
extern __IO uint16_t ADC_ConvertedValue;
void ADC_IRQHandler(void)
{
	if (ADC_GetITStatus(R_ADC,ADC_IT_EOC)==SET)			//获取ADC中断状态
    {
        ADC_ConvertedValue = ADC_GetConversionValue(R_ADC);			// 等待转换完成后,读取ADC的转换值
    }
    ADC_ClearITPendingBit(R_ADC,ADC_IT_EOC);				//清除状态寄存器
}

输出结果如下,调整电位器会发现数值在0V~3.3V之间变化。
在这里插入图片描述

单通道相对比较简单,这里先了解一下,后面在学习一下多通道并且启用DMA传输模式。

STM32F407是STMicroelectronics公司推出的一款高性能、低功耗的微控制器,它内置了一些模拟数字转换器(ADC),可以将模拟信号转换为数字信号进行处理。其中,温度传感器是ADC模块内置的一个传感器,可以用来测量芯片的温度。 要使用STM32F407的ADC模块进行温度转换,需要先开启ADC的时钟,并对ADC进行配置,具体操作步骤如下: 1. 开启ADC时钟:在RCC寄存器中设置ADC的时钟使能位。 2. 配置ADC:设置ADC的采样时间、分辨率、转换模式等参数。 3. 配置温度传感器:使能温度传感器,并设置温度传感器的采样时间。 4. 启动ADC转换:启动ADC的转换过程。 5. 读取转换结果:当转换完成后,从ADC数据寄存器中读取转换结果。 下面是一个简单的代码示例,以使用PA0作为温度传感器输入通道为例: ``` //开启ADC1时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //配置GPIOA0为模拟输入 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); //配置ADC ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); //配置温度传感器 ADC_TempSensorVrefintCmd(ENABLE); ADC_VBATCmd(ENABLE); //启动转换 ADC_Cmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN)); //等待ADC准备就绪 //读取转换结果 ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles); ADC_SoftwareStartConv(ADC1); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待转换完成 uint16_t adc_value = ADC_GetConversionValue(ADC1); //读取转换结果 ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放学校门口见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值