stm32 模数转换器-ADC单通道中断

ADC 模拟-数字转换器

ADC可以将引脚上连续变换的模拟电压转换成内存中存储的数字变量,建立模拟电路到数字电路的桥梁

12位逐次逼近型ADC,1us转换时间

输入电压:0~3.3V,转换结果范围:0~4095

18个输入通道,可测量16个外部(16个GPIO口)和2个内部信号源(内部温度传感器,内部参考电压)

规则组和注入组两个转换单元

模拟看门狗自动检测输入电压范围     

通道分配  

 

外部16个通道在转换时又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4路

规则通道:规则通道就是规矩意思,平时一般使用的通道

注入通道:插入,一种不安分的通道,是一种在规则通道转换的时候强行插入要转换的一种,这点和中断很像,只有在规则通道存在的时候才出现

 配置时钟,6.3.2时钟配置RCC_CFGF中ADCPRE位

 设置采样时间寄存器

 数据寄存器

 

 1.16位有效,用于存放独立模式转换完成数据

2.ADC_CR2,ALIGN

3.高16位是双ADC模式

 电压通过ADC转换存放在DR中

江科大回顾
ADC:模拟-数字转换器

12位逐次逼近 ADC,1us转换时间=1MHz

输入电压范围0~3.3V,转换结果范围:0~4095

18个输入通道

规则组和注入组两个转换单元

16个通道对应的GPIO口

 

连续转换:不需要手动转换

 

 尽量右对齐

         

 

ADC初始化结构体和常用固件库函数讲解

typedef struct
{
  uint32_t ADC_Mode;                      /*ADC工作模式*/
  FunctionalState ADC_ScanConvMode;       /*ADC扫描(多通道)或者单次(单通道)模式选择*/
  FunctionalState ADC_ContinuousConvMode; /*ADC单次转换或连续转换选择*/
  uint32_t ADC_ExternalTrigConv;          /*外部触发转换*/
  uint32_t ADC_DataAlign;                 /*数据寄存器对齐格式*/
  uint8_t ADC_NbrOfChannel;               /*ADC采集通道数 */
}ADC_InitTypeDef;

    // ADC 模式配置
    // 只使用一个ADC,属于独立模式
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 

    // 禁止扫描模式,多通道才要,单通道不需要
    ADC_InitStructure.ADC_ScanConvMode = DISABLE ;

    // 不用外部触发转换,软件开启即可
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

    // 转换结果右对齐
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

    // 转换通道1个
    ADC_InitStructure.ADC_NbrOfChannel = 1;    

几个常见的固件库函数

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

配置ADC时钟为PCLK2的8分频,即9MHz,设置采样时间

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);

// 配置 ADC 通道转换顺序和采样时间

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);

//软件触发

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

//外部触发

void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

编程要点:

一.独立模式-单通道-中断读取

1. 初始化ADC用到的GPIO

2.初始化ADC初始化结构体

3.配置ADC时钟,配置通道的转换顺序和采样时间

4.使能ADC转换完成中断,配置中断优先级

5.使能ADC,准备开始转换

6.校准ADC

7.软件触发ADC,真正转换开始

8.编写中断服务函数,读取ADC转换数据

9.编写main函数,把转换数据打印出来

#include "bsp_adc.h"

__IO uint16_t ADC_ConvertedValue;


/**
  * @brief  ADC GPIO 初始化
  * @param  无
  * @retval 无
  */
static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 打开 ADC IO端口时钟
	ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
	
	// 配置 ADC IO 引脚模式
	// 必须为模拟输入
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	
	// 初始化 ADC IO
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

/**
  * @brief  配置ADC工作模式
  * @param  无
  * @retval 无
  */
static void ADCx_Mode_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure;	

	// 打开ADC时钟
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// ADC 模式配置
	// 只使用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	
	// 禁止扫描模式,多通道才要,单通道不需要
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 

	// 连续转换模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

	// 不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

	// 转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	
	// 转换通道1个
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
		
	// 初始化ADC
	ADC_Init(ADCx, &ADC_InitStructure);
	
	// 配置ADC时钟为PCLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// 配置 ADC 通道转换顺序和采样时间
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, 
	                         ADC_SampleTime_55Cycles5);
	
	// ADC 转换结束产生中断,在中断服务程序中读取转换值
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	
	// 开启ADC ,并开始转换
	ADC_Cmd(ADCx, ENABLE);
	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	// ADC开始校准
	ADC_StartCalibration(ADCx);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx));
	
	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

static void ADC_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
	// 优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  // 配置中断优先级
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}


/**
  * @brief  ADC初始化
  * @param  无
  * @retval 无
  */
void ADCx_Init(void)
{
	ADCx_GPIO_Config();
	ADCx_Mode_Config();
	ADC_NVIC_Config();
}
/*********************************************END OF FILE**********************/
#ifndef __ADC_H
#define	__ADC_H


#include "stm32f10x.h"

// ADC 编号选择
// 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的
#define    ADC_APBxClock_FUN             RCC_APB2PeriphClockCmd
#define    ADCx                          ADC2
#define    ADC_CLK                       RCC_APB2Periph_ADC2

// ADC GPIO宏定义
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响
#define    ADC_GPIO_APBxClock_FUN        RCC_APB2PeriphClockCmd
#define    ADC_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADC_PORT                      GPIOC
#define    ADC_PIN                       GPIO_Pin_1
// ADC 通道宏定义
#define    ADC_CHANNEL                   ADC_Channel_10

// ADC 中断相关宏定义
#define    ADC_IRQ                       ADC1_2_IRQn
#define    ADC_IRQHandler                ADC1_2_IRQHandler

//#define    ADC_IRQ                       ADC3_IRQn
//#define    ADC_IRQHandler                ADC3_IRQHandler


void ADCx_Init(void);


#endif /* __ADC_H */



void ADC_IRQHandler(void)
{	
	if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET) 
	{
		// 读取ADC的转换值
		ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
	}
	ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}


// ADC 单通道采集,不使用DMA,一般只有ADC2才这样使用,因为ADC2不能使用DMA

#include "stm32f10x.h"
#include "bsp_usart.h"
#include "bsp_adc.h"

extern __IO uint16_t ADC_ConvertedValue;

// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal;        

// 软件延时
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
} 

/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{	
	// 配置串口
	USART_Config();
	
	// ADC 初始化
	ADCx_Init();
	
	printf("\r\n ----这是一个ADC单通道中断读取实验----\r\n");
	
	while (1)
	{
		ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; 
	
		printf("\r\n The current AD value = 0x%04X \r\n", 
		       ADC_ConvertedValue); 
		printf("\r\n The current AD value = %f V \r\n",
		       ADC_ConvertedValueLocal); 
		printf("\r\n\r\n");

		Delay(0xffffee);  
	}
}
/*********************************************END OF FILE**********************/







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值