欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32笔记之 ADC(模数转换)

程序员文章站 2022-03-06 08:08:20
...

写在前面:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。

 

目录

一、模拟量和数字量

二、ADC介绍

三、功能特征

四、转换模式

五、数据对齐方式

六、数据计算

七、代码实现


 

一、模拟量和数字量

在开篇之前,先来了解点硬件知识

模拟(类比)信号:在时间和数值上均具有连续性,即对应于任意时间值 t均有确定的函数值 u或 i,并且 u或 i的幅值是连续取值的

STM32笔记之 ADC(模数转换)

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

STM32笔记之 ADC(模数转换)

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

STM32笔记之 ADC(模数转换)

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

 

二、ADC介绍

STM32笔记之 ADC(模数转换)

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

 

三、功能特征

STM32笔记之 ADC(模数转换)

STM32笔记之 ADC(模数转换)

 

四、转换模式

1、单次转换模式

STM32笔记之 ADC(模数转换)

2、连续转换模式

STM32笔记之 ADC(模数转换)

 

五、数据对齐方式

1、右对齐

STM32笔记之 ADC(模数转换)

2、左对齐

STM32笔记之 ADC(模数转换)

 

六、数据计算

在上面我们获取到 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;

float Get_ADC_Result(void);
void ADCx_Init(void);


#endif	/* __BSP_ADC_H */


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

 

mian.c 文件

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include "bsp.h"
#include "bsp_uart.h"
#include "bsp_adc.h"


const uint32_t Baudrate_1 = 115200;		// 波特率设置	支持的波特率:115200,19200,9600,38400,57600,1200,2400,4800

/************************************************
函数名称 : main
功    能 : 主函数入口
参    数 : 无
返 回 值 : 无
*************************************************/
int main(void)
{	
    /* Initial Configuration */
    SystemInit();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SysTick_Init();
    UART1_Comfig(Baudrate_1);
    ADCx_Init();
	
    /* -------- End -------- */

	
    /* Infinite loop */
    while (1)
    {
        Get_ADC_Result();
        Delay_us(0x3FFFF);
    }
}

 

在上面的例程中,使用了 DMA请求,在这里你不需要去深究它,下一篇会对它进行讲解

相关标签: STM32 stm32 adc