Stm32 ADC学习
stm32 ADC 简介
stm32的ADC是 12位逐次逼近型 模拟数字转换器;它包括18个通道,可以用来测量16个外部通道和2个内部通道.ADC转换的结果存放在16位数据寄存器(ADC规则数据寄存器,ADC_DR 和 ADC注入数据寄存器,ADC_JDCx)中,这个数据寄存器可以设置对齐方式为左对齐或右对齐.
ADC通道与GPIO对应表(图片来自整点原子STM32F1开发指南库函数版本)

规则通道组和注入通道组
注入通道可打断规则通道的转换
所谓规则通道组和注入通道组其实应该就是通道的分组吧,按照OOP的思想来理解,通道组是一个基类,注入通道组和规则通道组派生自通道组这个基类,通道组这个基类中包含了一个保存各个通道的数组.
为什么要对通道进行分组呢,这个有待深究,以后再说.
ADC相关的寄存器
ADC_CR1
各个位描述如下图:

- scan位:
设置扫描模式,1为使用扫描模式,0则关闭.扫描模式下,有ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换,此时如果设置了EOCIE或JEOCIE,则只有在最后一个通道转换完毕后才会产生EOC或JEOC中断 - DUALMOD位:
设置ADC的操作模式,详细的看下面的来自<<stm32中文参考手册>>截图

ADC_CR2
各个位描述如下图:

- ADON位:用于开关AD转换器
- CONT位:用于设置是否进行连续转换,使用单次转换CONT位必须设置为0.
- EXTSEL[2:0]:用于选择启动规则转换组转换的外部事件

如果需要使用软件触发,就将这三个位设置为 111
ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2)
各个位描述如下图:

这两个寄存器用来设置通道0~17的采样时间,每个通道要占3位.

对于每个要转换的通道,采样时间尽量长一点,以获得较高的准确度,但是会降低ADC的转换速率.ADC的转换时间可以由以下公式计算:
Tconv = 采样时间 + 12.5周期
ADC规则序列寄存器(ADC_SQR1~3)
这几个寄存器功能都差不多,不一一详细说明了.

- L[3:0]:用于存储规则序列的长度
ADC数据寄存器(ADC_DR)
这个没什么好说的,用来存放AD转换后的结果
要注意可以通过ADC_CR2的ALIGN位设置这个寄存器是左对齐还是右对齐
ADC状态寄存器(ADC_SR)
没啥好说的,保存了各种状态,看图吧.

通过库函数配置ADC1通道1进行AD转换
查看手册可以知道ADC1通道1对应着PA1,如下图

1.外设使能
- STM32F103ZET6的ADC通道1在PA1上所以我们先要使能 PORTA的时钟 和 ADC1时钟,然后设置 PA1为模拟输入.
2.复位ADC1,同时设置ADC1的分频因子
- 开启了ADC1的时钟后,要复位ADC1,将ADC1的全部寄存器重设位缺省值,然后通过RCC_CFGR设置ADC1的分频因子,并且分频因子要确保ADC1的时钟不超过14MHz!
//ADC复位 ADC_DeInit();
RCC_ADCCLKConfig(RCC_PCLK2_DIV6); //设置分配因子的库函数
3.初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息.
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);// ADC初始化
4.使能ADC并校准
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); //使能指定的ADC
void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准
while(ADC_GetResetCalibrationStatus(ADCx));//等待复位校准结束
void ADC_StartCalibration(ADC_TypeDef* ADCx);//执行ADC校准
while(ADC_GetCalibrationStatus(ADCx));//等待AD校准结束
5.设置规则序列1里面的通道,读取ADC的值
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); //设置规则序列通道以及采样周期
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//允许软件开启ADC转换
while(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EOC));//等待转换结束
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//获取转 换结果数据
MDK5中实现代码
配置stm32f103库函数编程环境,我用的是正点原子的那一套,不多记录了;
ADC1_Init() 函数
void ADC1_Init(void)
/* ---------------------------------------------
ADC1_IN1 -> PA.1
--------------------------------------------- */
void ADC1_Init(void)
{
GPIO_InitTypeDef gpioInitStruct;
ADC_InitTypeDef adcInitStruct;
//Enable periph clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//配置ADC的时钟,不要超过14MHz;
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
//Congfig PA.1
gpioInitStruct.GPIO_Mode = GPIO_Mode_AIN; //设置PA.1的输入模式为模拟输入
gpioInitStruct.GPIO_Pin = GPIO_Pin_1;
gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gpioInitStruct);
//ADC1 复位
ADC_DeInit(ADC1);
//initialize adc1
adcInitStruct.ADC_Mode = ADC_Mode_Independent; //ADC模式:ADC独立模式
adcInitStruct.ADC_DataAlign = ADC_DataAlign_Right; //ADC_DR寄存器的数据对齐方式:右对齐
adcInitStruct.ADC_ScanConvMode = DISABLE; //是否允许连续扫描模式:不允许,使用单通道模式
adcInitStruct.ADC_ContinuousConvMode = DISABLE; //单次转换模式
adcInitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC触发方式:不需要外部触发源,由软件触发
adcInitStruct.ADC_NbrOfChannel = 1; //进行转换的ACD通道数目
ADC_Init(ADC1,&adcInitStruct);
//Enable ADC1
ADC_Cmd(ADC1,ENABLE);
//ADC1校准
ADC_ResetCalibration(ADC1); //复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成
ADC_StartCalibration(ADC1); //ACD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待ADC校准完成
}
ADC_GetConvValue()
u16 ADC_GetConvValue(u8 channel)
/**
* 获取指定的通道adc的转换结果
* @param channel: 指定adc的通道,必须在1~3之间
*/
u16 ADC_GetConvValue(u8 channel)
{
//Config sample channel
//采样周期尽量设置长一些,以确保精度
ADC_RegularChannelConfig(ADC1,channel,1,ADC_SampleTime_239Cycles5);
//使能软件转换
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
ADC_GetAverageConvValue()
u16 ADC_GetAverageConvValue(u8 channel,u8 times)
u16 ADC_GetAverageConvValue(u8 channel,u8 times)
{
u8 i = 0;
u32 temp = 0;
for(;i < times;i++)
{
temp += ADC_GetConvValue(channel);
}
return (u16)(temp/times);
}
ADC_SampleValue2ReadableValue()
double ADC_SampleValue2ReadableValue(u16 sampleValue)
/**
* 描述:将AD转换后存放在ADC_DR寄存器中的值转换为有意义的值,
* 可以通过宏定义 REF 来设置参考电压
* @param sampleValue : 要转换的值
* @retval 转换的结果,是一个double类型的浮点数
*/
double ADC_SampleValue2ReadableValue(u16 sampleValue)
{
return (double)sampleValue*((double)REF/4096.0);
}
main.c文件代码
main.c
#include"ADC.h"
#include"delay.h"
#include"usart.h" void Init(void);
void Loop(void); int main(void)
{
Init();
while(1)
Loop();
} void Init(void)
{
delay_init();
USART_Debug_Init();
ADC1_Init();
USART_WriteLine("系统初始化完成!将开始AD采集.");
} void Loop(void)
{
u16 sampledValue;
sampledValue = ADC_GetAverageConvValue(1,5);
USART_WriteLine("采样值: %d ; 计算所得电压值: %.2f ",sampledValue,ADC_SampleValue2ReadableValue(sampledValue));
delay_ms(250);
}在main.c中使用的 USART_WriteLine(const char*str,...)函数 是我自己封装的串口函数,也可以使用正点原子 System文件夹 下提供的printf()函数;
总结库函数配置ADC的步骤
1.使能需要用到的GPIO 和 ADC的时钟;
2.配置ADC的时钟分频:
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);
2.配置IO口,输入模式为 GPIO_Mode_AIN,模拟输入模式;
3.调用ADC_DeInit();对ADC进行复位;
4.调用ADC_Init();初始化ADC
5.调用ADC_Cmd(ADCx,ENABLE);,使能ADC
6.校准ADC:
ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成 ADC_StartCalibration(ADC1); //ACD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待ADC校准完成
7.获取AD转换的结果
</div>
Stm32 ADC学习的更多相关文章
- DSP28377S - ADC学习编程笔记
DSP28377S - ADC学习编程笔记 彭会锋 2016-08-04 20:19:52 1 ADC类型导致的配置区别 F28377S的ADC类型是Type 4类型,我的理解是不同类型的ADC采 ...
- STM32 ADC 采样 频率的确定
一 STM32 ADC 采样频率的确定 1. : 先看一些资料,确定一下ADC 的时钟: (1),由时钟控制器提供的ADCCLK 时钟和PCLK2(APB2 时钟)同步.CLK 控制器为A ...
- 关于STM32 ADC自校准的个人理解
前几天发过一篇帖子,叫:关于STM32 ADC自校准的个人理解文章大体说的是自校准前要先将ADON位置1,之后再校准. 本以为彻底的了解了自校准的过程,但是昨天晚上无意间看到了一个函数说明,不禁愁云又 ...
- STM32 FSMC学习笔记+补充(LCD的FSMC配置)
STM32 FSMC学习笔记+补充(LCD的FSMC配置) STM32 FSMC学习笔记 STM32 FSMC的用法--LCD
- stm32定时器学习二——PWM设置
/* STM32 嵌入式学习入门(5)——PWM的实现 上一篇博文介绍了定时器和PWM的基本的原理,本篇博文从代码层面来介绍PWM的具体实现.同样,还是以博主所用的开发板——正点原子开发板STM32F ...
- STM32 ADC多通道转换DMA模式与非DMA模式两种方法(HAL库)
一.非DMA模式(转) 说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/arti ...
- 基于STM32的学习型通用红外遥控设备的设计实现(三)
CPU: STM32 调试平台: STM32F103ZET和STM32F103VBT 软件平台: Keil uVision4 电路设计: Altium Designer v6.9 http://blo ...
- STM32 ADC多通道规则采样和注入采样
layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 什么是ADC? STM ...
- 【转载-Andrew_qian】stm32中断学习
[转载]stm32中断学习 中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大 ...
随机推荐
- ASP.NET中修改从数据库获取的datatable中的值
有些时候,我们从数据库表中获取一个实体的对象,但有些内容并不是最终显示的内容,格式也都是不一样.经过一番尝试,发现datatable中的数值如果跟想要改变的类型不一致,就无法更改,只有添加新列,然后把 ...
- vs2008 FileUpload 上传控件 Gridview传多个值
拖fileupload控件,控件后加button1 lable1 lable2,还要在与本窗体同意目录下新建img文件夹protected void Button1_Click(object send ...
- 网页flash播放代码
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100%" hei ...
- PHP-GTK的demo在windows下运行出现的问题
I am trying to use Firebird 2.5.2.26539 with wamp,When i enable the extensions of firebird in php: - ...
- IETF
一.简介 https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E5%B7%A5%E7%A8%8B%E4%BB%BB%E5%8A%A1%E ...
- UI设计如何做好排版?你可以学习一下格式塔原理
格式塔是一种视觉感知的理论,是研究人们视觉如何将元素组织成群体或整体,从而视觉上进行分类,在设计中,我们使用格式原理能使得我们设计更科学性,更具吸引力.通过格式塔效应,去处理设计中的点.线.面.颜色. ...
- Laravel中用GuzzleHttp
阅读数:14715 今天项目中用到GuzzleHttp,开始不知道怎么用,其实还是很简单的. 直接在项目根目录,输入以下命令 composer require guzzlehttp/guzzle 1 ...
- python的介绍和及基本的使用
一 什么是计算机 1 计算机就是由一堆硬件组成的一个机器. 2 硬件的分类: CPU:犹如人类的大脑,运行着需要运行的程序. 内存:将 CPU要运行的内容从硬盘中读取出来,然后CPU在内存里拿内容,只 ...
- 2018.09.15 hdu1599find the mincost route(floyd求最小环)
传送门 floyd求最小环的板子题目. 就是枚举两个相邻的点求最小环就行了. 代码: #include<bits/stdc++.h> #define inf 0x3f3f3f3f3f3f ...
- hdu-1055(贪心)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1055 题意:给一棵树涂色,这棵树的每个节点都有自己的价值Ci,涂色的原则是只由这个节点的父节点涂色之后 ...