STM32 ADC采样

这篇具有很好参考价值的文章主要介绍了STM32 ADC采样。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.基础概念

2.原理:ADC采样过程分为四步:采样、保持、量化、编码。

3.采样定理

4.采样保持放大器(SHA)

5.ADC电压值转换

6.ADC轮询采样


1.基础概念

ADC 全称:Analog-to-Digital Converter,指模拟/数字转换器,就是将模拟信号转换成数字信号

STM32 ADC采样

①模拟信号:是连续变化的,具有电路简单,分辨率很高的特点,抗噪声能力弱

②数字信号:是离散变化的,抗噪声能力强,便于存储和交换,可用于加密

STM32 ADC采样

2.原理:ADC采样过程分为四步:采样、保持、量化、编码。

①采样是指将模拟波形在时域上进行切分,每个切片大小大致等于原来的波形的值,这过程往往回丢失一些信息

②采样保持:如果被采样的模拟信号的变化频率相对于A/D转换器的速度来说比较高,为保证转换精度,需要在A/D转换之前加上采样保持电路,使得在A/D转换期间保持输入模拟信号不变。

③量化:在采样完后给每个时间片分配一个数字,这样的过程称为量化

④编码: 量化后的数值还需通过编码用一个二进制代码表示出来,经过编码后得到的就是AD转换结果的数字量,二进制编码的位宽等于ADC的位宽。

STM32 ADC采样

3.采样定理

 又称奈奎斯特采样定理,即当采样频率fs大于采样信号最高频率fmax的两倍时,采样后的数字信号完整地保留了原始信号中的信息。公式 :fs>2*fn

4.采样保持放大器(SHA)

采样保持过程将已采样的模拟电压在一段必要的时间内保持恒定,以便让ADC将模拟电压转换成数字形式。

一个基本的SHA如图,开始的时候模拟开关闭合,通过输入缓冲放大器对模拟电压进行采样,电容C存储或保存采样电压一段时间,输出缓冲放大器提供一个高输入阻抗来防止电容快速掉电。ADI要求输出缓冲器的输入阻抗足够高,以便电容可以保持时间内放电少于1LSB

STM32 ADC采样

5.ADC电压值转换

1.首先确定ADC是几位的,即确定最大数值是多少。比如一个8位的ADC,最大值是0xFF,就是255。
(一般芯片手册会有说明)

2.然后确定最大值时对应的参考电压值。一般而言最大值对应3.3V。这个你需要看这个芯片ADC模块的说明。寄存器中有对于输入信号参考电压的设置。

3.计算电压,读取的ADC数值除以最大数值再乘以参考电压值。比如你ADC值为0x55,那么实际值就是0x55/(0xFF+1)*3.3V = 1.65V

4.验证计算值。你可以用电压表量一下对应的引脚,看看计算值和实际值是否一样。


/********************************************************/

/**        AT89C52+ADC0832+LCD1602                     **/

/**       用ADC0832采集电压,并在1602上显示电压值                  **/

/********************************************************/

 

#include <reg52.h>

#include <intrins.h>

typedef unsigned int u16;

typedef unsigned char u8;

 

bit RW=0;

sbit RS=P2^7;

sbit EN=P2^6; 

sbit CLK=P1^0;

sbit DIO=P1^1;

sbit CS=P1^3;

 

u8 len;

u8 Display_Buffer[4];

void LcdInit();

void delay_us(u8 us);

void delay_ms(u8 ms);

void LcdDisplay(u8 x,u8 y, u8 *str);

void LcdSetCursor(u8 x,u8 y);

void LcdStar();

void write_con(u8 con);

void write_dat(u8 dat);

 

u8 Get_AD_Result()

{

    u8 i;

    u8 data1=0,data2=0;

    CS=0;

    

  //第一个下降沿到来前,DI需置1,起始控制位,开始转换

    CLK=0;DIO=1; _nop_();   

    CLK=1;_nop_();

    

 //第二个下降沿到来前,设D=1/0,选择单端/差分(SGL/DIF)模式中的单端输入模式

    CLK=0;DIO=1; _nop_();  

    CLK=1;       _nop_();     

 

 //第三个下降沿到来前,设D=0/1,选择CH0/CH1,这里选择单通道ch0  

    CLK=0;DIO=1; _nop_();   

    CLK=1;DIO=0; _nop_();  

    

 //第四个下降沿到来前,DI =1 

    CLK=0;DIO=1; _nop_();

    

//4-11,共8个下降沿 DO输出转换信号,读取数据(MSB-->LSB) 

    for(i=0;i<8;i++)

    {

        CLK=1;_nop_();

        CLK=0;_nop_();

       data1=(data1<<1)|(u8)DIO;

    }

//11-18,共8个下降沿,读取数据(LSB)-->MSB) 

    for(i=0;i<8;i++)

    {

        data2=data2|((u8)DIO<<i);

        CLK=1;_nop_();

        CLK=0;_nop_();

    }

    CS=1;

    //如果MSB-->LSB和LSB)-->MSB读取数据结果相同,返回读取结果,否则0

    return(data1==data2)?data1:0;

}

 

//-----------------------------------------

//    主函数

//-----------------------------------------

void main()

{

    u8 Data;

	LcdInit();

    LcdStar();

	while(1)

	{

        //获取AD转换值 最大值255对应最高电压5.000v 显示三个数 使用500

        Data =Get_AD_Result()*500.0/255;

		Display_Buffer[0]= Data/100+'0'; 

		Display_Buffer[1]= '.';

		Display_Buffer[2]=Data/10%10+'0'; 

		Display_Buffer[3]=Data%10+'0';

		LcdDisplay(9,1, Display_Buffer);

 

	}

}

 

//-----------------------------------------

//   延时us和1ms函数

//-----------------------------------------

void delay_us(u8 us)

{

	while(us--);

}

	

void delay_ms(u8 ms)

{

	while(ms--)

	{

		delay_us(248);

		delay_us(248);

	}

}

 

//-----------------------------------------

//    lcd1602显示

//-----------------------------------------

//lcd初始化

void LcdInit()

{

	write_con(0x01);//清屏

	write_con(0x38);//设置16*2显示,配置8位数据接口

    write_con(0x38);//设置16*2显示,配置8位数据接口

	write_con(0x0C);//开显示,光标关,闪烁关,去黑块

	write_con(0x06);//写数据时光标右移,画面不动

	

}

void LcdStar()

{

    u8 code str[]="Voltage measure";

    u8 tab[]="Voltage=";

    LcdInit();                    //初始化1602液晶  

    LcdDisplay(1,0,str);

    LcdDisplay(1,1,tab);

    LcdDisplay(9,1,"...");        //默认初始化温度00

    LcdDisplay(13,1,"V");         //添加V电压

}

//设置显示RAM 起始地址,亦即光标位置,(x,y)对应屏幕上的起始坐标

void LcdSetCursor(u8 x,u8 y)

{

    u8 addr;

    if(y==0)    //由输入的屏幕坐标计算显示RAM的地址

        addr=0x00+x;    //第一行字符地址从0x00起始

    else

        addr=0x40+x;    //第二行字符地址从0x40起始

    write_con(addr|0x80);   //设置RAM地址

        

}

//设置显示RAM 起始地址,亦即光标位置,(x,y)对应屏幕上的起始坐标,str-字符串指针

void LcdDisplay(u8 x,u8 y,u8 *str)

{

    LcdSetCursor(x,y); //设置起始地址  

	while(*str !='\0')  //连续写入字符串数据,直到检测到结束符

	{

		write_dat(*str++);  //先取str指向的数据,然后str自加1

		delay_us(100);

		

	}

}

 

//lcd1602写指令

void write_con(u8 con)

{

	P0=con;

	RS=0;

	RW=0;

	EN=1;

	delay_us(200);

	EN=0;

}

 

//lcd1602写数据

void write_dat(u8 dat)

{

	P0=dat;

	RS=1;

	RW=0;

	EN=1;

	delay_us(200);

	EN=0;

}

 

6.ADC轮询采样

在STM32 ADC轮询转换通道中,下一个通道开启时前一个通道不需要手动关闭,ADC会自动切换到下一个通道进行采集。

ADC轮询转换通道的原理和过程:

ADC(Analog-to-Digital Converter)是模拟信号转换为数字信号的电路。在STM32中,ADC是一个十分重要的外设,它可以将模拟信号转换为数字信号,供微处理器进行处理。

ADC的转换方式有多种,其中轮询转换通道是最基本的一种,它的原理是:在一次转换完成之后,自动切换到下一个通道进行采集,直到所有通道采集完成,然后产生一个转换结束的中断。

下面是一个简单的ADC轮询转换通道的代码示例:

  1. 初始化ADC模块:设置ADC通道和转换模式等参数,以及开启ADC时钟。

  2. 获取采样数据:通过设置ADC转换模式为单次转换或连续转换,轮流对3个通道进行采样,将采样结果存储到缓冲区中。

  3. 数据处理:将采样结果进行处理,比如进行滤波、校准等操作,得到最终的采样数据。

  4. 计算采样时间和定采样周期:采样时间是指从开始采样到采样结束所需的时间,可以通过软件延时或硬件定时器实现。采样周期是指两次采样之间的时间间隔,可以根据需要进行设置。

以下是单次采样的代码实现和注释,把三个通道的数据都放在一个缓冲区:

#include "bf7006_adc.h"

#define ADC_BUFFER_SIZE 16      // 缓冲区大小
#define ADC_SAMPLE_TIME 10      // 采样时间,单位为ms
#define ADC_SAMPLE_PERIOD 100   // 采样周期,单位为ms

static uint16_t adc_buffer[ADC_BUFFER_SIZE];   // 采样数据缓冲区
static uint8_t adc_buffer_index = 0;           // 缓冲区索引

/**
 * @brief 初始化ADC模块
 */
void adc_init(void)
{
    HAL_ADC_ConfigChannel(&hadc, ADC_CHANNEL_0, ADC_MODE_SINGLE);    // 配置ADC通道0为单次转换模式
    HAL_ADC_ConfigChannel(&hadc, ADC_CHANNEL_1, ADC_MODE_SINGLE);    // 配置ADC通道1为单次转换模式
    HAL_ADC_ConfigChannel(&hadc, ADC_CHANNEL_2, ADC_MODE_SINGLE);    // 配置ADC通道2为单次转换模式
    HAL_ADC_Start(&hadc);   // 开启ADC转换
}

/**
 * @brief 获取采样数据
 */
void adc_sample(void)
{
    HAL_ADC_Start(&hadc);   // 开始转换
    HAL_ADC_PollForConversion(&hadc, ADC_SAMPLE_TIME);  // 等待转换完成
    adc_buffer[adc_buffer_index++] = HAL_ADC_GetValue(&hadc);   // 保存采样结果
    if (adc_buffer_index >= ADC_BUFFER_SIZE) {    // 缓冲区已满,重置索引
        adc_buffer_index = 0;
    }
}

/**
 * @brief 数据处理
 */
uint16_t adc_process_data(void)
{
    uint16_t result = 0;
    for (uint8_t i = 0; i < ADC_BUFFER_SIZE; i++) {   // 对所有采样数据进行求和
        result += adc_buffer[i];
    }
    result /= ADC_BUFFER_SIZE;  // 求平均值
    return result;
}

/**
 * @brief 计算采样周期
 */
uint32_t adc_calculate_period(void)
{
    return ADC_SAMPLE_PERIOD - ADC_SAMPLE_TIME;   // 采样周期减去采样时间即为等待时间
}

开发板的ADC模块有三个通道,可以通过轮询的方式进行连续转换采样。下面是采样原理和过程:

采样原理:

ADC模块将模拟信号转换为数字信号,采样过程中需要注意采样精度和采样速率。采样精度指的是数字信号的位数,采样速率指的是每秒钟采样的次数。

采样过程:

1. 初始化ADC模块,设置ADC通道和采样精度;
2. 设置ADC转换模式为连续转换模式;
3. 启动ADC转换;
4. 轮询ADC转换完成标志位,读取ADC转换结果;
5. 对采样数据进行处理和计算。

下面是代码注释及解析:


#include "stm32f10x.h"

#define ADC1_DR_Address    ((uint32_t)0x4001244C) // ADC1数据寄存器地址

uint16_t ADC_ConvertedValue[3]; // 存储ADC采样结果

void ADC_Configuration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能ADC1和GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置PA0、PA1、PA2为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // ADC1配置
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 开启扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 开启连续转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不使用外部触发转换
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 3; // 采样通道数为3
    ADC_Init(ADC1, &ADC_InitStructure);

    // 配置ADC1通道0、1、2为采样通道
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);

    // 使能ADC1
    ADC_Cmd(ADC1, ENABLE);

    // ADC1校准
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));
}

void ADC_Sampling(void)
{
    uint8_t i;

    // 开始转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    // 等待转换完成
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

    // 读取采样结果
    for (i = 0; i < 3; i++)
    {
        ADC_ConvertedValue[i] = ADC_GetConversionValue(ADC1);
    }

    // 清除转换完成标志位
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}

int main(void)
{
    ADC_Configuration();

    while (1)
    {
        ADC_Sampling();
    }
}

在上面的代码中,我们通过`ADC_Configuration()`函数初始化ADC模块,设置ADC通道,ADC转换模式。然后,在`adc_sampling()`函数中,启动ADC转换,我们通过轮询ADC转换完成标志位,读取ADC转换结果,并将采样数据存储到数组中。最后,在`adc_process()`函数中,我们对采样数据进行处理和计算。

关于采样时间和采样周期的计算,可以根据采样精度和采样速率进行计算。采样时间可以通过以下公式计算:

采样时间 = 1 / 采样速率

采样周期可以通过以下公式计算:

采样周期 = 采样时间 x 采样次数

在实际应用中,我们可以根据需要调整采样精度和采样速率,以满足应用的要求。文章来源地址https://www.toymoban.com/news/detail-443804.html

到了这里,关于STM32 ADC采样的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 多路ADC同时扫描采样

    在项目实际应用中,刚好有需求需要使用多路ADC同时采样,这里就选择STM32 ADC多路ADC同时采样,这里简单说明下配置过程,以及使用步骤 如下图所示,使用四路ADC输入 ADC_Voltage - 电压信号的采样,外部输入信号,交流电的输入信号,正选信号 ADC_Current - 电流电流的采样,外部

    2024年02月06日
    浏览(43)
  • stm32教程之三重ADC交错采样

    ps:本文基于stm32F407ZGT6单片机         stm32F4单片机单通道采集的最大采样率为2.4M,所以有时会难以满足较高频率的采样,于是查阅芯片手册,发现stm32F4支持多重ADC采集,利用每个通道的转换时间,错位采样,从而提高采样率,最大把采样率开到2.4*3=7.2M.  (去年初学AD

    2024年02月12日
    浏览(40)
  • 基于STM32的ADC采样序列频谱分析

      本文主要介绍对ADC采集得到的数字序列进行FFT频谱分析。   确定采样率除了要遵守奈奎斯特采样定律意外还需要考虑一些问题。在数字系统中,我们只能进行一些有限的离散的运算,对于有限长的序列,我们不可能拿它去做DTFT,只能做DFT。这就需要 把有限长序列也当

    2024年02月13日
    浏览(42)
  • STM32--ADC数值采样/附ADC采集热敏传感器使用

    目录 一丶ADC介绍 二丶ADC工作原理及管脚分布 三丶代码部分详解 (一)库函数介绍 (二)代码部分整合         ADC模块中文名为模拟/数字转换器,是12位逐次逼近型的模拟数字转换器,一般用于数值的采样   可以将引脚上连续变化的模拟电压转换为内存中存储的数字变

    2024年02月03日
    浏览(45)
  • 搭建stm32电机控制代码框架(三)——Stm32CubeMx配置ADC采样

    电机控制另一个关键的模块就是ADC采样,这个模块配置的好坏决定了采样电流和电压的精准度,因此有必要对其进行深入学习。 简介: STM32 在片上集成的ADC 外设非常强大。STM32F103xC、STM32F103xD 和STM32F103xE增强型产品内嵌3个12位的ADC,每个ADC 共用多达 21 个外部通道,可以实现

    2024年02月13日
    浏览(41)
  • STM32双路ADC注入通道和规则通道采样

    电机控制使用四路注入通道采集,参考ST官方库,使用定时器10us触发一次,使用ADC1和ADC2各2路注入通道。 需要一路ADC进行规则采样油门信号,使用中断的话会和注入通道中断放在同一个函数里面 ,我不喜欢,所以使用了DMA中断。 PreKnowledge: 规则通道:最多16个规则通道,采样

    2024年04月14日
    浏览(46)
  • STM32-ADC电压采样实验(寄存器版)

    STM32F10X系列支持三路ADC,其ADC通道及对应IO口如下表所示: 其能接受的电压输入范围一般为0-3.3V(V REF- ≤ V IN ≤ V REF+ ),因此,如果需要测量超出0-3.3v量程范围的电压数据,需要在外围硬件增加分压电阻,将电路转换到0-3.3V量程范围内再进行采集。 这里用于做ADC采集的引脚使

    2024年02月15日
    浏览(52)
  • STM32 ADC单/多通道采样+DMA搬运

    通过介绍我们可以了解到,ADC是12位的转换器,所以采样值范围是0~4095。18个通道可同时进行转换,也可以单独转换某个通道。 使用ADC的流程应为: 初始化IO口。 我这里使用的是PA1进行采样,也就是ADC1的通道1 初始化ADC。 转换、获取采样值。 多通道的时候我们一般用DMA来搬

    2024年02月14日
    浏览(48)
  • STM32CubeMX配置ADC采样(轮询、中断、DMA)

    STM32CubeMX能够极大减小STM32外设配置的工作量,因此作者也借助空闲时间对STM32CubeMX相关配置进行了学习,本文介绍如何利用STM32CubeMX配置ADC采样,记录了作者学习过程中遇到的问题及解决办法,使大家少走弯路,并方便以后复习 先选择所使用的MCU,这里我使用的是STM32F407ZGT系

    2024年02月03日
    浏览(51)
  • STM32F3系列 ADC采样单端采样模式(基于LL库)

    芯片型号:STM32f303RBT6 开发软件:MDK5 CubeMX VS Code 目录 STM32F3系列 ADC 单端采样(基于LL库) 目录 引言 1 基础知识 1.1ADC转换基本流程 1.2 时钟树 1.3 关键参数 1.3.1 位数 1.3.2 触发信号 1.3.3 采样时间 1.3.4 转换时间 2 CubeMx 配置步骤 2.1 确定输入通道 2.2 配置ADC 2.3 输出设置 2.4 MD5 设置

    2024年02月08日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包