STM32——13.ADC模数转换器

AD简介

  • ADC(Analog-Digital Converter)模拟-数字转换器。

  • ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

  • 12位逐次逼近型ADC,1us转换时间。

  • 输入电压范围:0~3.3V,转换结果范围:0~4095

  • 18个输入通道,可测量16个外部和2个内部信号源。

  • 规则组和注入组两个转换单元。

  • 模拟看门狗自动监测输入电压范围。

  • STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道。

  • 逐次逼近型ADC:

  • ADC基本结构:

  • 输入通道:

  • 通道ADC1ADC2ADC3
    通道0PA0PA0PA0
    通道1PA1PA1PA1
    通道2PA2PA2PA2
    通道3PA3PA3PA3
    通道4PA4PA4PF6
    通道5PA5PA5PF7
    通道6PA6PA6PF8
    通道7PA7PA7PF9
    通道8PB0PB0PF10
    通道9PB1PB1
    通道10PC0PC0PC0
    通道11PC1PC1PC1
    通道12PC2PC2PC2
    通道13PC3PC3PC3
    通道14PC4PC4
    通道15PC5PC5
    通道16温度传感器
    通道17内部参考电压
  • 转换模式:看PPT,图片太多了。

  • 触发控制:

  • 数据对齐(一般右对齐):

  • 转换时间:

    1. AD转换的步骤:采样,保持,量化,编码。

    2. STM32 ADC的总转换时间为: TCONV = 采样时间 + 12.5个ADC周期

    3. 例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期 TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs。

  • 校准:

    1. ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。

    2. 建议在每次上电后执行一次校准。

    3. 启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期。

  • 硬件电路:

  • code show:

    //单通道
    -------------------AD.c-----------------------------------------------------------------------
    #include "stm32f10x.h"                  // Device header
    ​
    void AD_Init(void)
    {
        //第一步,开启RCC时钟,AD和GPIO的
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        //ADCCLK配置。72MHz / 6 = 12MHz
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        //第二步,配置GPIO,配置为模拟输入模式
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //第三步,配置多路开关 , 输入通道(这里选择了0,如果需要多个复制即可)。
        ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
        
        //第四步,配置ADC转换器
        ADC_InitTypeDef ADC_InitStructure;
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //使用右对齐
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        
        ADC_Init(ADC1,&ADC_InitStructure);
        
        
        //第五步,开关控制,开启ADC,ADC_Cmd函数,最好在校准一下
        ADC_Cmd(ADC1 , ENABLE);
        //校准
        ADC_ResetCalibration(ADC1);
        while(ADC_GetResetCalibrationStatus(ADC1) == SET);
        ADC_StartCalibration(ADC1);
        while(ADC_GetCalibrationStatus(ADC1) == SET);
        
    }   
    ​
    uint16_t AD_GetValue(void)
    {
        ADC_SoftwareStartConvCmd(ADC1 , ENABLE);
        while(ADC_GetFlagStatus(ADC1 , ADC_FLAG_EOC) == RESET);
        return ADC_GetConversionValue(ADC1);
    }
        
    -------------------AD.h-----------------------------------------------------------------------
    #ifndef _AD_H
    #define _AD_H
    ​
    void AD_Init(void);
    uint16_t AD_GetValue(void);
    ​
    #endif    
    -------------------main.c---------------------------------------------------------------------
    #include "stm32f10x.h"   
    #include "OLED.h"
    #include "AD.h"
    #include "Delay.h"
    ​
    uint16_t ADValue;
    float Volatge;
    int main(void)
    {
        OLED_Init();
        AD_Init();
        OLED_ShowString(1,1,"ADValue:");
        OLED_ShowString(2,1,"Volatge:0.00");
        
        while(1)
        {
            ADValue = AD_GetValue();
            Volatge = (float)ADValue /4095 * 3.3;
            OLED_ShowNum(1,9,ADValue,4);
            OLED_ShowNum(2,9,Volatge,1);
            OLED_ShowNum(2,11,(uint16_t)(Volatge * 100)%100,2);
            Delay_ms(100);
        }
    }
            

  • code show:

    -------------------AD.c-----------------------------------------------------------------------
    //多通道
    #include "stm32f10x.h"                  // Device header
    ​
    void AD_Init(void)
    {
        //第一步,开启RCC时钟,AD和GPIO的
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        //ADCCLK配置。72MHz / 6 = 12MHz
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        //第二步,配置GPIO,配置为模拟输入模式
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //第三步,配置多路开关 , 输入通道(这里选择了0,如果需要多个复制即可)。
        
        //第四步,配置ADC转换器
        ADC_InitTypeDef ADC_InitStructure;
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //使用右对齐
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        
        ADC_Init(ADC1,&ADC_InitStructure);
        
        
        //第五步,开关控制,开启ADC,ADC_Cmd函数,最好在校准一下
        ADC_Cmd(ADC1 , ENABLE);
        //校准
        ADC_ResetCalibration(ADC1);
        while(ADC_GetResetCalibrationStatus(ADC1) == SET);
        ADC_StartCalibration(ADC1);
        while(ADC_GetCalibrationStatus(ADC1) == SET);
        
    }   
    ​
    uint16_t AD_GetValue(uint8_t ADC_Channel)
    {
        ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);
        ADC_SoftwareStartConvCmd(ADC1 , ENABLE);
        while(ADC_GetFlagStatus(ADC1 , ADC_FLAG_EOC) == RESET);
        return ADC_GetConversionValue(ADC1);
    }
    ​
    -------------------AD.h-----------------------------------------------------------------------
    #ifndef _AD_H
    #define _AD_H
    ​
    void AD_Init(void);
    uint16_t AD_GetValue(uint8_t ADC_Channel);
    ​
    #endif    
    -------------------main.c---------------------------------------------------------------------  
    #include "stm32f10x.h"   
    #include "OLED.h"
    #include "AD.h"
    #include "Delay.h"
    ​
    uint16_t AD0,AD1,AD2,AD3;
    ​
    int main(void)
    {
        OLED_Init();
        AD_Init();
        OLED_ShowString(1,1,"AD0:");
        OLED_ShowString(2,1,"AD1:");
        OLED_ShowString(3,1,"AD2:");
        OLED_ShowString(4,1,"AD3:");
        
        while(1)
        {
            AD0 = AD_GetValue(ADC_Channel_0);
            AD1 = AD_GetValue(ADC_Channel_1);
            AD2 = AD_GetValue(ADC_Channel_2);
            AD3 = AD_GetValue(ADC_Channel_3);
            
            OLED_ShowNum(1, 5, AD0, 4);
            OLED_ShowNum(2, 5, AD1, 4);
            OLED_ShowNum(3, 5, AD2, 4);
            OLED_ShowNum(4, 5, AD3, 4);
            Delay_ms(100);
        }
    }
            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_48261292

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值