ADC模数转换+实验

2023-10-25 01:20
文章标签 实验 adc 模数转换

本文主要是介绍ADC模数转换+实验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ADC概述:

Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。

STM32F10x ADC特点:

  • 12位逐次逼近型的模拟数字转换器。
  • 最多带3个ADC控制器
  • 最多支持18个通道,可最多测量16个外部和2个内部信号源。
  • 支持单次和连续转换模式
  • 转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。
  • 通道0到通道n的自动扫描模式
  • 自动校准
  • 采样间隔可以按通道编程
  • 规则通道和注入通道均有外部触发选项
  • 转换结果支持左对齐或右对齐方式存储在16位数据寄存器
  • ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)
  • ADC供电要求:2.4V-3.6V
  • ADC输入范围:VREF- ≤ VIN ≤ VREF+

3个ADC控制器:

file


其中144脚芯片因为带PF脚,所以多5个通道,为21个外部通道。
小于144脚芯片只有16个外部通道。

 

STM32F10x系列芯片ADC通道和引脚对应关系:

file

ADC引脚:

file

ADC框图:

file


file

 

STM32通道组

1,规则通道组:相当正常运行的程序。最多16个通道。
规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则
组转换的总数应写入ADC_SQR1寄存器的L[3:0]中
2,注入通道组:相当于中断。最多4个通道。
注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组
里转化的总数应写入ADC_JSQR寄存器的L[1:0]中

 

file

STM32F1的ADC的各通道可以单次,连续,扫描或者间断模式执行。

  • 单次转化 VS 连续转换:

    file


    file

 

区别:单次转换不会自动启动另一次转换,但是连续转换会。

  • 扫描模式

    file


    file

 

ADC中断及其配置函数讲解:

ADC中断

file

ADC时钟配置

file


不要让ADC时钟超过14MHz,否则可能不准。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);

寄存器:

ADC_CR1寄存器

file

  • ADC_CR2寄存器

    file

 

ADC的采样时间

file


最小转换时间:1us(ADC时钟=14MHz,采样周期为1.5周期下得到)

 

  • ADC_SQR1/SQR2/SQR3规则序列寄存器

     

    file


    先确定序列长度(最多16),再确定转换(4个)。

  • ADC_JSQR注入系列寄存器

     

    file

     

  • ADC_DR规则通道数据寄存器

    file

  • ADC_JDR注入通道数据寄存器

    file

  • ADC_SR状态寄存器

    file

常用库函数:

ADC初始化函数ADC_Init:

typedef struct
{uint32_t ADC_Mode;//ADC模式:配置ADC_CR1寄存器的位[19:16]  :DUALMODE[3:0]位FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONTuint32_t ADC_ExternalTrigConv;  //触发方式:ADC_CR2的位[19:17] :EXTSEL[2:0]               uint32_t ADC_DataAlign;   //对齐方式:左对齐还是右对齐:ADC_CR2的位11:ALIGN        uint8_t ADC_NbrOfChannel;//规则通道序列长度:(寄存器)ADC_SQR1的位[23:20]: L[3:0]      
}ADC_InitTypeDef;
COPY

例程:

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE;   //不开启扫描 
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发软件 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); 
COPY

ADC使能函数 ADC_Cmd():

    void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);ADC_Cmd(ADC1, ENABLE);  //使能指定的ADC1COPY

ADC使能软件转换函数 ADC_SoftwareStartConvCmd

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx,FunctionalState NewState)
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动
COPY

ADC 规则通道配置函数ADC_RegularChannelConfig

 void ADC_RegularChannelConfig(ADC_TypeDef* ADCx,uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1,ADC_SampleTime_239Cycles5 );//参数:通道一,序列1,采样周期239.5
COPY

ADC 获取转换结果函数ADC_GetConversionValue

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
ADC_GetConversionValue(ADC1);//获取ADC1转换结果COPY

常用库函数:

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//ADC初始化
void ADC_DeInit(ADC_TypeDef* ADCx)//ADC参数配置函数
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//时钟ADC使能
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);//使能ADC中断
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//软件开启转换
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);//配置规则通道(采样时间等)
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//获取转换结果//一些校准函数
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
COPY

实验

目的:ADC1的通道1(PA1)进行单次转化

步骤:

1,开启PA口时钟和ADC1时钟,设置PA1为模拟输入。
GPIO_Init();
APB2PeriphClockCmd();
2,复位ADC1,同时设置ADC1分频因子。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_DeInit(ADC1);
3, 初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef ADCx, ADC_InitTypeDef ADC_InitStruct);
4, 使能ADC并校准。
ADC_Cmd(ADC1, ENABLE);
5, 配置规则通道参数:
ADC_RegularChannelConfig();
6,开启软件转换:ADC_SoftwareStartConvCmd(ADC1);
7,等待转换完成,读取ADC值。
ADC_GetConversionValue(ADC1);

手写代码:

ADC.h

#ifndef __ADC_H
#define __ADC_H 
#include "sys.h"void Adc_Init(void);//声明初始化函数(步骤1-4)
u16  Get_Adc(u8 ch); //获取通道转换结果(步骤5-7)
u16 Get_Adc_Average(u8 ch,u8 times); //多次调用Get_Adc的函数#endif 
COPY

ADC.c:

#include "adc.h"#include "delay.h"//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3                                                                     
void  Adc_Init(void)
{   ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;//第一步RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );   //使能ADC1通道时钟,或可以写成两行//PA1 作为模拟通道输入引脚                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;               //PA1GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       //模拟输入引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50Mhz;   GPIO_Init(GPIOA, &GPIO_InitStructure);   //第二步ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M//第三步ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC工作模式:ADC1和ADC2工作在独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE;   //模数转换工作在单通道模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //ADC数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   //第四步ADC_Cmd(ADC1, ENABLE);  //使能指定的ADC1ADC_ResetCalibration(ADC1); //使能复位校准  while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束ADC_StartCalibration(ADC1);  //开启AD校准while(ADC_GetCalibrationStatus(ADC1));   //等待校准结束//  ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能}   //第五步     
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{//设置指定ADC的规则组通道,一个序列,采样时间ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );//ADC1,ADC通道,采样时间为239.5周期                 //第六步ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADC1);    //返回最近一次ADC1规则组的转换结果
}//第七步
u16 Get_Adc_Average(u8 ch,u8 times)
{u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times;
}    
COPY

main.c:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"     
#include "adc.h"int main(void){   u16 adcx;float temp;delay_init();            //延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级uart_init(115200);      //串口初始化为115200LED_Init();              //LED端口初始化LCD_Init();             Adc_Init();             //ADC初始化POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,200,16,16,"Elite STM32");    LCD_ShowString(60,70,200,16,16,"ADC TEST");   LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(60,110,200,16,16,"2015/1/14"); //显示提示信息POINT_COLOR=BLUE;//设置字体为蓝色LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:");        LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V");           while(1){adcx=Get_Adc_Average(ADC_Channel_1,10);LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值temp=(float)adcx*(3.3/4096);adcx=temp;LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值temp-=adcx;temp*=1000;LCD_ShowxNum(172,150,temp,3,16,0X80);LED0=!LED0;delay_ms(250);  }}
COPY

现象:

LCD液晶屏上显示ADC的值和电压值,可放到不同的点位测试ADC和电压值。

 本文转载自:ADC模数转换+实验 – 布尔博客

欢迎关注技术公众号,获取更多硬件学习干货!

我们能为你提供什么?

技术辅导:C++、Java、嵌入式软件/硬件

项目辅导:软件/硬件项目、大厂实训项目

就业辅导:就业全流程辅导、技术创业支持

对接企业HR:培养输送优质性人才

这篇关于ADC模数转换+实验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/279066

相关文章

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

61.以太网数据回环实验(4)以太网数据收发器发送模块

(1)状态转移图: (2)IP数据包格式: (3)UDP数据包格式: (4)以太网发送模块代码: module udp_tx(input wire gmii_txc ,input wire reset_n ,input wire tx_start_en , //以太网开始发送信

LTspice模拟CCM和DCM模式的BUCK电路实验及参数计算

关于BUCK电路的原理可以参考硬件工程师炼成之路写的《 手撕Buck!Buck公式推导过程》.实验内容是将12V~5V的Buck电路仿真,要求纹波电压小于15mv. CCM和DCM的区别: CCM:在一个开关周期内,电感电流从不会到0. DCM:在开关周期内,电感电流总会到0. CCM模式Buck电路仿真: 在用LTspice模拟CCM电路时,MOS管驱动信号频率为100Khz,负载为10R(可自

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

学习硬件测试05:NTC(ADC)+正弦波(DAC)+DMA(ADC+DAC)(P73、P76、P78)

文章以下内容全部为硬件相关知识,鲜有软件知识,并且记的是自己需要的部分,大家可能看不明白。 一、NTC(ADC) 1.1实验现象 本实验用 NTC 采集温度,数码管实时显示温度数据(整数),左下角 USB 小串口每隔 1S 打印温度信息。 1.2硬件电路 NTC 电阻是一个模拟温度传感器,随着温度的升高,电阻值逐渐减小。电路简单介绍如下: 电源滤波电容在 25℃ 室温下 NTC 电

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

STM32CubeMX 2 解锁ADC模块

掏出上次写完的project。选择引脚 选择PA4和ADC1_IN4 2.选择设置配置 3.发现改完前面的配置之后这里的时钟自动变成了56, 选定,改回72. 4.改configuration,双击ADC1 跳出如下界面: Mode 选independent mode Data Alignment选Right Aligment是为了方便读数,因为这是一个12位的AD

pta-2024年秋面向对象程序设计实验一-java

文章申明:作者也为初学者,解答仅供参考,不一定是最优解; 一:7-1 sdut-sel-2 汽车超速罚款(选择结构) 答案: import java.util.Scanner;         public class Main { public static void main(String[] arg){         Scanner sc=new Scanner(System