数字(数位)信号:在时间和数值上均具有离散性,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;


**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**