1.前言
上一篇文章介绍了USART串口通信的内容,这篇文章我们来介绍一下STM32单片机中的ADC采集部分,并且使用串口与上位机进行通信,显示采集的电压值。同样地,我们所使用的硬件设备仍然是STM32RCT6单片机等基础设备,关于单片机的原理图在前文均已详细介绍,这里我们就不再赘述。
2.ADC详解
定义
ADC是模拟到数字转换器(Analog-to-Digital Converter)的缩写。它是一种电子设备或模块,用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统(如微处理器、微控制器等)能够对其进行处理和分析。
模拟信号是连续变化的电压或电流信号,其数值在一定范围内变化。而数字信号是由一系列离散的数字表示,只能取有限的值,通常以二进制形式表示。
工作原理
ADC的工作原理是将模拟信号分割成一系列离散的取样,并将每个取样值转换为相应的数字表示。这个过程涉及到两个主要步骤:采样和量化。
采样:ADC将连续变化的模拟信号在一定时间间隔内进行取样。取样频率决定了每秒采集的样本数,通常以赫兹(Hz)表示。采样过程通过保持并测量模拟信号在每个采样时间点的电压值来实现。
量化:采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。这通常通过比较采样值与参考电压之间的差异,并将其转换为数字表示。
ADC的分辨率是指它可以将模拟信号分成多少个离散的级别。较高的分辨率意味着ADC能够提供更精细的数字表示,从而更准确地捕捉和量化模拟信号的细微变化。
ADC功能描述
如图为ADC的功能框图
3.软件部分
ADC初始化
ADC初始化用到初始化函数:
ADCx_Init();
这个函数包含三条语句:
ADCx_GPIO_Config();
ADC_NVIC_Config();
ADCx_Mode_Config();
接下来我们分别看看这三条语句的内容。
ADC GPIO配置
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_APBxClock_FUN(ADC_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
}
这个函数中主要是ADC引脚的初始化,并且设置IO口为模拟输入模式。
ADC MODE 配置
static void ADCx_Mode_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_APBxClock_FUN(ADC_CLK,ENABLE );
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;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADCx, &ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
ADC_Cmd(ADCx, ENABLE);
ADC_ResetCalibration(ADCx);
while(ADC_GetResetCalibrationStatus(ADCx));
ADC_StartCalibration(ADCx);
while(ADC_GetCalibrationStatus(ADCx));
ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}
这里主要是配置ADC的采样模式,先设置了ADC为连续转换模式,转换通道数为1,初始化ADC。然后配置ADC时钟为PCLK2的8分频,也就是9MHz,配置ADC转换顺序为1,第一个转换,采样时间为55.5个时钟周期,最后开启ADC,并且开始转换。
ADCx NVIC 配置
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ADCx_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
这里主要是ADC的NVIC配置,NVIC的相关原理在前面的文章已经详细介绍,这里不再赘述。
4.完整代码
Main.c
#include "stm32f10x.h"
#include "bsp/usart/bsp_debug_usart.h"
#include "bsp/adc/bsp_adc.h"
float ADC_ConvertedValueLocal;
extern __IO uint16_t ADC_ConvertedValue;
static void Delay(uint32_t time);
int main(void)
{
DEBUG_USART_Init();
ADCx_Init();
printf("----ÕâÊÇÒ»¸öADCµ¥Í¨µÀµçѹ²É¼¯ÊµÑé-----\n");
while (1)
{
ADC_ConvertedValueLocal =(float)ADC_ConvertedValue*3.3/4096;
printf("ADת»»Ôʼֵ = 0x%04X \r\n", ADC_ConvertedValue);
printf("¼ÆËãµÃ³öµçѹֵ = %f V \r\n",ADC_ConvertedValueLocal);
Delay(1000);
}
}
static void Delay(uint32_t time)
{
uint32_t i,j;
for(i=0;i<time;++i)
{
for(j=0;j<10000;++j)
{
}
}
}
bsp_adc.c
#include "bsp/adc/bsp_adc.h"
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_APBxClock_FUN(ADC_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
}
static void ADCx_Mode_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_APBxClock_FUN(ADC_CLK,ENABLE );
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;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADCx, &ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
ADC_Cmd(ADCx, ENABLE);
ADC_ResetCalibration(ADCx);
while(ADC_GetResetCalibrationStatus(ADCx));
ADC_StartCalibration(ADCx);
while(ADC_GetCalibrationStatus(ADCx));
ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ADCx_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void ADCx_Init(void)
{
ADCx_GPIO_Config();
ADC_NVIC_Config();
ADCx_Mode_Config();
}
bsp_adc.h
#ifndef __ADC_H__
#define __ADC_H__
#include <stm32f10x.h>
#define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
//#define ADCx ADC1
//#define ADC_CLK RCC_APB2Periph_ADC1
//#define ADCx_IRQ ADC1_2_IRQn
//#define ADC_IRQHandler_FUN ADC1_2_IRQHandler
//#define ADCx ADC2
//#define ADC_CLK RCC_APB2Periph_ADC2
//#define ADCx_IRQ ADC1_2_IRQn
//#define ADC_IRQHandler_FUN ADC1_2_IRQHandler
#define ADCx ADC3
#define ADC_CLK RCC_APB2Periph_ADC3
#define ADCx_IRQ ADC3_IRQn
#define ADC_IRQHandler_FUN ADC3_IRQHandler
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADC_PORT GPIOC
#define ADC_PIN GPIO_Pin_0 //
#define ADC_CHANNEL ADC_Channel_10 //
//#define ADC_PIN GPIO_Pin_1 //
//#define ADC_CHANNEL ADC_Channel_11 //
void ADCx_Init(void);
#endif /* __ADC_H__ */
5.实验效果
ADC
6.结束语
本次实验讲解了使用Stm32的ADC采集内容,这也是STM32单片机应用很多的一部分内容,希望以上内容对各位朋友有所帮助。
最后,欢迎大家在评论区留言批评指正。谢谢!