STM32笔记之 ADC(模数转换)_adc convertedvalue 梅40,2024年最新2024年物联网嵌入式开发笔试题总结

50 阅读4分钟

数字(数位)信号:在时间和数值上均具有离散性,u或 i的变化在时间上不连续,总是发生在离散的瞬间,且它们的数值是一个最小量值得整数倍,并以此倍数作为数字信号的数值

所以,所谓的 ADC转换实际就是把模拟信号的模拟量转换成数字信号的数字量

同样的,DAC则是反过来把数字信号的数字量变成模拟信号的模拟量

 

二、ADC介绍

从数据手册上我们可以了解到,我们实验所用的 ADC转换,它的采样数据最多支持 12bit(即:2^12 = 4096个数据),有多达18个通道,可测量 16个外部和 2个内部信号源。各通道的 A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在 16位数据寄存器中。

 

三、功能特征

 

四、转换模式

1、单次转换模式

2、连续转换模式

 

五、数据对齐方式

1、右对齐

2、左对齐

一般情况下,我们都是用右对齐这种规则,因为它是数据补 0,只占用 12个 bit;如果使用左对齐,那么还得往右移 4位。

 

六、数据计算

在上面我们获取到 ADC是 12位分辨率,也就是说总的有 12bit的数值,然而,我们最终需要的是电压值,所以要进行数据换算,这个可以参考以前那篇 ADC采样值转化成电压值详解

值得注意的是,数据类型一定要处理好,必要时要强制转换一下数据类型,否则会出现计算不准的情况。

 

七、代码实现

bsp_adc.c 源文件

#include "bsp_adc.h"
#include "bsp_uart.h"


// ADC1转换的电压值通过MDA方式传到SRAM
__IO uint16_t ADC_ConvertedValue;

/************************************************
函数名称 : Get_ADCx_Result
功    能 : ADC数据获取
参    数 : Ch ---- 通道
返 回 值 : temp ---- 转换计算后的电压值(放大 1000倍)
*************************************************/
float Get_ADC_Result(void)
{
	float temp;

	temp =(float) ADC_ConvertedValue / 4096*VDD_VALUE;	// 读取转换的 AD值

#if 1
	printf(">>>>> 电压值:%d\r\n",(int)temp);
	
#endif

	return temp;                 
}

/************************************************
函数名称 : ADCx_GPIO_Config
功    能 : ADC GPIO配置
参    数 : 无
返 回 值 : 无
*************************************************/
static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* Enable ADCxGPIO clock */
	ADC_GPIO_APBxClock_FUN(ADC_GPIO_CLK, ENABLE);
	
	/* Configure PB.00 (ADC Channel8) as analog input */
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

/************************************************
函数名称 : ADCx_Mode_Config
功    能 : ADC模式配置
参    数 : 无
返 回 值 : 无
*************************************************/
static void ADCx_Mode_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	/* Enable DMA1 clock */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	/* Enable ADCx clock */
	ADC_APBxClock_FUN(ADC_CLK, ENABLE);
	
	/* Restoration DMA ADC Channel*/
	DMA_DeInit(ADC_DMA_CHANNEL);
	
	/* DMA init structure parameters values */
	DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t )(&(ADCx->DR));	
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;	
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	
	DMA_InitStructure.DMA_BufferSize = 1;	
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 	
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;	
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
	
	/* Enable DMA ADC channel */
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
	
	/* ADC init structure parameters values */
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;      // 设置 ADC模式,因为只使用一个ADC,属于单模式
	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;	                // 转换通道 1个		
	ADC_Init(ADCx, &ADC_InitStructure);
	
	/* ADCCLK = PCLK2/8 */
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	
	/* ADCx regular channel configuration */
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
	/* Enable ADCx DMA */
	ADC_DMACmd(ADCx, ENABLE);
	
	/* Enable ADCx */
	ADC_Cmd(ADCx, ENABLE);
	
	/* Enable ADCx reset calibration register */  
	ADC_ResetCalibration(ADCx);
	/* Check the end of ADCx reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	/* Start ADCx calibration */
	ADC_StartCalibration(ADCx);
	/* Check the end of ADCx calibration */
	while(ADC_GetCalibrationStatus(ADCx));
	
	/* Start ADCx Software Conversion */
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

/************************************************
函数名称 : ADCx_Init
功    能 : 各 ADC口初始化
参    数 : 无
返 回 值 : 无
*************************************************/
void ADCx_Init(void)
{
	ADCx_GPIO_Config();
	ADCx_Mode_Config();
}


/*---------------------------- END OF FILE ----------------------------*/



 

bsp_adc.h 头文件

#ifndef __BSP_ADC_H
#define __BSP_ADC_H


#include "stm32f10x.h"

#define VDD_VALUE	3300

// 注意:用作 ADC采集的 IO必须没有复用,否则采集电压会有影响
/******************** ADC1输入通道(引脚)配置 **************************/
#define    ADCx                          ADC1
#define    ADC_APBxClock_FUN(x, y)       RCC_APB2PeriphClockCmd(x, y)
#define    ADC_CLK                       RCC_APB2Periph_ADC1

#define    ADC_GPIO_APBxClock_FUN(x, y)  RCC_APB2PeriphClockCmd(x, y)
#define    ADC_GPIO_CLK                  RCC_APB2Periph_GPIOC

#define    ADC_PORT                      GPIOC
#define    ADC_PIN                       GPIO_Pin_1

#define    ADC_CHANNEL                   ADC_Channel_11
#define    ADC_DMA_CHANNEL               DMA1_Channel1

extern __IO uint16_t ADC_ConvertedValue;



![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/b4b0d48adeb543dbba67b4e794ba976b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1770653665&x-signature=rKsBND7A6mLR0SJTvaElsn%2FaG9A%3D)
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/fb02b1b5d2934b9f9ca48972a1fe3125~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1770653665&x-signature=nbwQvUELbHHlg4X%2BsWrhjM1SxdM%3D)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**