STM32F103单片机ADC功能使用

发布者:平和宁静最新更新时间:2022-01-27 来源: eefocus关键字:STM32F103  单片机  ADC功能 手机看文章 扫描二维码
随时随地手机看文章

12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。


模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。


ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。


ADC 主要特征


● 12位分辨率


● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断


● 单次和连续转换模式


● 从通道0到通道n的自动扫描模式


● 自校准


● 带内嵌数据一致性的数据对齐


● 采样间隔可以按通道分别编程


● 规则转换和注入转换均有外部触发选项


● 间断模式


● 双重模式(带2个或以上ADC的器件)


下面就用代码演示如何设置ADC单次转换模式


void ADCx_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    ADC_InitTypeDef ADC_InitStructure;


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5; //PA1

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    ADC_DeInit(ADC1);


    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_InitStructure.ADC_NbrOfChannel = 1; //规则转换ADC通道数

    ADC_Init(ADC1, &ADC_InitStructure);


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


    ADC_ResetCalibration(ADC1); //复位校准

    while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束

    ADC_StartCalibration(ADC1); //开启AD校准

    while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束


}


首先初始化IO口,这里的初始化的是ADC抓换通道的0–5,对应的IO口PA0到PA5,将这6个IO口这是为模拟输入模式。接下来在将这几个口设置为ADC口,在设置之前首先将ADC模式复位,然后将ADC设置为单通道单词转换模式,也就是每次只转换一个通道,转换一次后就停止转换,直到接收到下一次转换命令为止。开始转换的命令是由软件来设置的。


ADC口初始化好之后,还需要一个读取转换结果的函数,用于读取指定通道的转换值。


//获取ADC值

//ch:通道号

u16 Get_Adc( u8 ch )

{

    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;

}


Get_Adc()函数用于读取指定通道的ADC转换值,这里的通道必须是初始化函数中初始化过的通道,这个函数每次只读取一次通道值,为了确保转换结果的正确性,需要多次读取通道值取平均值,所以这里Get_Adc_Average()函数就是用来设置多次读取指定通道值,然后取平均值后返回。比如可以设置读取通道1,100次然后取平均值。ADC相关的设置函数就初始化好了,接下来在主函数中调用Get_Adc_Average()函数就可以读取通道值了。


int main(void)

{

    u16 adcx = 0;

    float temp;

    delay_init();        //延时函数初始化

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    uart_init(115200);

    LED_Init();



    LED0 = 1;

    LED1 = 1;

    delay_ms(500);

    LED0 = 0;

    LED1 = 0;


    ADCx_Init();


    printf("ADC test!!!rn");

    while(1)

    {

        adcx = Get_Adc_Average(ADC_Channel_0, 10);

        printf("ch0       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch0 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_1, 10);

        printf("ch1       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch1 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_2, 10);

        printf("ch2       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch2 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_3, 10);

        printf("ch3       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch3 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_4, 10);

        printf("ch4       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch4 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_5, 10);

        printf("ch5       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch5 adc value: %drn", adcx);


        LED0 = !LED0;

        delay_ms(500);

    }

}


在主函数中依次读取通道0到通道5的值,读取10次取平均值,然后将转换后的值打印出来。由于ADC为12位,所以转换后的最大值为4096,对应的最大电压值为3.3V,为了方便观察,将转换后的值换换位电压值。

关键字:STM32F103  单片机  ADC功能 引用地址:STM32F103单片机ADC功能使用

上一篇:STM32F103单片机驱动蜂鸣器
下一篇:STM32单片机实现DMA+ADC+UART功能

推荐阅读最新更新时间:2024-11-10 12:52

加入低价战局 ST发售0.32美元32位元MCU
意法半导体(ST)发表售价达0.32美元32位元微控制器(MCU)。继英飞凌(Infineon)、恩智浦(NXP)及飞思卡尔(Freescale)之后,意法半导体亦推出首款价格逼近8位元的32位元MCU--STM32F030,并具备入门级32位元MCU中少见的功能,藉此大幅提升该款产品的性价比,准备大举抢攻8位元MCU市场。 意法半导体微控制器产品部产品行销经理Patrice Hamard表示,该公司借重制程、封装及测试最佳化的组合,开发出超低价入门级32位元MCU,准备积极抢攻8位元市场版图。系统客户经常面临效能和成本难以取舍的头痛问题,因此该公司发布兼具8位元价格与32位元性能优势的低价32位元MCU,助力系统业者设计出不
[单片机]
MSP430F5438A单片机基于SPI的FatFs移植笔记(一)
怎么说呢……太费劲了,前面的博客还烂尾了,主要是觉得自己在调试的过程当中思维太混乱。虽然说自己挖的坑,含着泪也要填上,这几个就先不填了吧我重新开个坑把调通的说清楚。 不管移植什么程序,最重要的就是, 不要自以为是 一定要先查资料,花一周查资料,查到查不到为止,否则你编了一半的程序再参考别人的,直接后果是你下不了决心推翻重来 1. FatFs移植要点: 相信能看到这个博客的都知道FatFs是什么了,目前应该是0.11版本,我就不多废话了,一个开源的文件系统,不全面的说,作用就是让你编程序操作写SD卡的内容能够被PC机读出来(有不对的话懂的大神请指正) 它的好处就是只要写底层的几个硬件驱动函数就OK了,上层的函数都已经写好了,
[单片机]
MSP430F5438A<font color='red'>单片机</font>基于SPI的FatFs移植笔记(一)
51单片机 8*8LED点阵横向流水 使用位运算生成中间帧
#include reg52.h typedef unsigned char uchar; sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; code uchar image = { {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //动画帧0 {0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3}, //动画帧8 {0xFF,0
[单片机]
基于飞思卡尔MCU的气囊(Airbag)方案
方案描述: 控制单元是安全气囊系统的核心组件,由16或32位MCU与一组局部加速度传感器组成。根据系统复杂程度可增加卫星传感器,通过外围设备接口5 (PSI5)和分布系统接口 (DSI) 等标准传感器总线提供辅助碰撞信息。经过处理的传感器数据可利用专用多通道点火驱动电路引爆前部、侧部和帘式气囊。 作为附加安全要素,高能效开关式电源组件可在发生事故电源连接中断的情况下,使系统保持工作几百毫秒。 飞思卡尔气囊系统产品符合汽车安全控制(AEC) AEC-Q100技术规范及其他关键汽车标准,提供世界一流的高质量汽车安全解决方案。 方案关键器件表: 方案设计图:
[嵌入式]
基于飞思卡尔<font color='red'>MCU</font>的气囊(Airbag)方案
PIC单片机控制LED点阵显示屏
本实验在proteus软件上模拟完成。 实验器件:20片8X8LED点阵显示屏,10片74LS164移位寄存器,10片74LS273数据锁存器,2片74LS138译码器,1片PIC16F877A单片机。 proteus元件库中中没有16X80点阵显示屏,所以用20片8X8LED点阵屏拼装而成。 10片74LS164移位寄存器和10片74LS273数据锁存器用于传送和保存一行数据。 2片74LS138构成4选16译码器用于行选。 实验截图: 源程序: list p=16f877A ; list directive to define processor #include p16f87
[单片机]
PIC<font color='red'>单片机</font>控制LED点阵显示屏
51单片机二进制转换
#include reg51.h #define LongToBin(n) \ (\ ((n 21) & 0x80) | \ ((n 18) & 0x40) | \ ((n 15) & 0x20) | \ ((n 12) & 0x10) | \ ((n 9) & 0x08) | \ ((n 6) & 0x04) | \ ((n 3) & 0x02) | \ ((n ) & 0x01) \ ) #define Bin(n) LongToBin(0x##n##l) void main(void) { unsigned char c; c = Bin(10101001); // c = 0xA9
[单片机]
51单片机子程序调用与返回指令简介及举例
(1)主程序与子程序 在前面的灯的实验中,我们已用到过了子程序,只是我们并没有明确地介绍。子程序是干什么用的,为什么要用子程序技术呢?举个例程,我们数据老师布置了10道算术题,经过观察,每一道题中都包含一个(3*5+2)*3的运算,我们能有两种选择,第一种,每做一道题,都把这个算式算一遍,第二种选择,我们能先把这个结果算出来,也就是51,放在一边,然后要用到这个算式时就将51代进去。这两种办法哪种更好呢?不必多言。设计程序时也是这样,有时一个功能会在程序的不一样地方反复使用,我们就能把这个功能做成一段程序,每次需要用到这个功能时就“调用”一下。  (2)调用及回过程:主程序调用了子程序,子程序执行完之后必须再回到主程序继续执行,不
[单片机]
PIC单片机在连续接收串口数据时遇到的小问题
关于PIC单片机串口数据接收,如果数据接口一直可以检测数据,那么即使关闭RCIE,实际上也会接收数据,当数据源源不断地进来时,你再使能RCIE的时候其实也只能接收到关闭之后的两个数据,此后再也无法进入中断。解决这样的方法为关闭引脚为串口的定义,让其成为普通引脚而非串口引脚。 格式为 PIE1&=0xdf; RCSTA&=0x7f;//关闭 PIE1|=0x20; RCSTA|=0x80;//开启 关于PIE和RCSTA置位的前后顺序其实也有关系,这样为正确顺序。 而在有限的时间内将接收到的数据进行处理时,数组的赋值比单个字符赋值的时间要长这因素也要被考虑到。
[单片机]

推荐帖子

MSP432 开箱+energytrace技术初体验
从X宝上购买的MSP432launchpad已经到货,大家分享一下。MSP432最大的优点是32位M4F核心+低功耗,launchpad上使用了XDS110调试器,可以支持energytrace技术,对功率进行测量。废话不说了,放图片大家欣赏一下。安装IDE,使用的是CCS6,默认安装了enerytrace软件。安装CCS完毕后,发现驱动已经更新成功打开CCS,选择了最简单的blink程序,进行调试。在调试窗口会看到energytrace的图标。点开后出现如下界面该界面
flyword 微控制器 MCU
通过USB向单片机传输信号可行吗?
通过USB向单片机传输信号可行吗?我想通过USB向单片机传入某一信号,再由单片机传出相应的电平信号,这个设想可行吗?有没有什么具体的实行方法?通过USB向单片机传输信号可行吗?一般使用usb供电,没见过使用usb传输信号,使用单片机的两个I/O引脚就可以实现,剩下的工作就是你的程序编写的事情了!输出的电平信号不是返还电脑,是给其他设备的,也就是说我想通过单片机把USB信号转换为电平信号!51单片机能做到这点吗?在51前加一D12,最终信号由51给电平信号我在网上查资料说D12会出现丢
lcllcl20031 嵌入式系统
学习嵌入式操作系统需要什么条件
我想先学一学嵌入式操作系统,但不知道学哪一个好,可能会先Linux吧。更重要的是,我不知道学习Linux需什么条件,特别是硬件,是不是只需要一台电脑就行呢?我就只有一台电脑,这样可以学Linux了吗?我还是个菜鸟,希望大家能给我一些建议,不胜感激!学习嵌入式操作系统需要什么条件应该有块开发板
www2900 嵌入式系统
PADS9.1下载
PADS9.1下载PADS9.1下载怎么上传不上去呢:Q最大可以支持15M,如果超过这个可能要分成几个包了回复沙发毛承玲的帖子谢谢,我知道了,;P;P;P文件太大了点回复沙发毛承玲的帖子這個文件至少上百M,建議找個地方上傳後,再把連結貼出來
毛承玲 PCB设计
恳求WinCE.Net下ASP调用文本文件方法
求WinCE.Net下ASP页面调用文本文件方法。小弟已试过在WinCE.NetASP页面中不能创建Scripting.FileSystemObject对象和ADODB.Stream对象,请问各位大侠还有没有别的方法在ASP中调用文本文件?先谢过了恳求WinCE.Net下ASP调用文本文件方法期待中
iyj WindowsCE
[BearPi-Pico H2821]测评 ⑥丢包及连接稳定性测试
上两篇我们查了一下SLEserver和client端的demo,怎么运行的,收发应该调用那些接口已经清楚了,就可以开始做丢包及连接稳定性测试了测试方案server端代码不用动,client端连接server后,创建一个TASK,定时用SLE向server发数据,并计数,发送到最大次数后,停止发送,摧毁task。然后提取双方日志,查看中途是否有断连、收发次数是否有缺少1.client端代码修改1.1发送函数参照之前找到的发送函数sle_ua
不爱胡萝卜的仓鼠 RF/无线
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved