重学STM32---(五)ADC
这两天把外部中断和ADC看了下,个人感觉外部中断不是很难,也就没有把记下来了,毕竟写这个挺浪费时间。ADC是比较复杂的,如果想让完全自由的运用ADC必须经过多次实践可能才可以。由于已经学过库函数,也就打算自己看数据手册写了一个简单的寄存器版的ADC,期间也遇到了很多问题,幸好都解决了。
把这次学习的重点都记下来,以后再看不知是什么感觉O(∩_∩)O哈哈~

1. 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。
2. 通过设置ADC_CR2寄存器的ADON位可给ADC上电。当第一次设置ADON位时,它将ADC从断
电状态下唤醒
3.AD转换模式:单次转换和连续转换 (单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位)
(在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换,在同一寄存器设置)
4.扫描模式:
此模式用来扫描一组模拟通道。
扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。
如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM中。而注入通道转换的数据总是存储在ADC_JDRx寄存器中。
5.可编程的通道采样时间:
ADC使用若干个ADC_CLK周期对输入电压采样,采样周期数目可以通过ADC_SMPR1和ADC_SMPR2寄存器中的SMP[2:0]位更改。每个通道可以分别用不同的时间采样。
总转换时间如下计算:
TCONV = 采样时间+ 12.5个周期
6.双ADC模式:(同步注入模式 ,同步规则模式 ,快速交叉模式 ,慢速交叉模式,交替触发模式,独立模式)
在双ADC模式里,根据ADC1_CR1寄存器中DUALMOD[2:0]位所选的模式,转换的启动可以是ADC1主和ADC2从的交替触发或同步触发。
注意: 在双ADC模式里,当转换配置成由外部事件触发时,用户必须将其设置成仅触发主ADC,从ADC设置成软件触发,这样可以防止意外的触发从转换。但是,主和从ADC的外部触发必须同时被激活。
在双ADC模式里,为了在主数据寄存器上读取从转换数据,必须使能DMA位,即使不使用DMA传输规则通道数据。
配置一个简单ADC程序的步骤:(单通道)
0.开启对应的IO口时钟和ADC时钟,在RCC_CFGR寄存器中给ADC分频,使之不超过14M...
1.在ADC_CR1寄存器中:设置独立模式(DUALMOD[3:0]:双模式选择 ),不使用扫描模式,允许产生EOC中断...其余默认就行
2.在ADC_CR2寄存器中:位SWSTART(开始转换规则通道,要转换时设置1),不用外部事件启动转换,位EXTSEL[2:0](选择启动规则通道组转换的外部事件,选择 111,软件触发),数据右对齐(左右随意),不使用DMA模式,单次转换模式,位ADON(开/关A/D转换器 )
3.ADC_SMPRx(ADC采样时间寄存器):自己看实际情况设置就行(总转换时间如下计算:TCONV = 采样时间+ 12.5个周期)
4.ADC_SQR1寄存器:默认0就行了(因为就一个通道)
5.在中断服务函数中检查ADC_SR寄存器中EOC位,为1时用软件清除,然后进行下一步
6.在ADC_DR寄存器中读数据
注意:初始化ADC时要校准,在ADC_CR2寄存器中设置校准
程序:
学习库函数写了一个时常要修改数据的结构体,这样重写另一个ADC也就方便了许多,只要修改结构体的值就行 但我这个还不是很好
adc.h
#ifndef _ADC_H_
#define _ADC_H_
typedef enum
{
disable = 0,
enable = !disable
}STATE;
typedef struct
{
unsigned int ADC_ModeSel; //双模式选择
STATE ADC_ScanModeSel; //是否开启扫描模式
unsigned int ADC_ExternalTrigConv; //外部触发方式
unsigned int ADC_DatdAlign; //数据对齐方式
STATE ADC_DMAEN; //是否使用DMA
STATE ADC_ContinuousCon; //是否连续转换
unsigned char ADC_NumRegularchan; //规则转换通道个数
}ADC_STRUCT;
extern ADC_STRUCT ADC_STRUCTInit ;
unsigned short Get_Value(unsigned char ch);
void Adc1_Chan1_Init();
#endif
adc.c
#include "adc.h"
#include "stm32f10x.h"
#include "delay.h"
ADC_STRUCT ADC_STRUCTInit =
{
0x0, //独立模式
disable, //不开启扫描模式
0x000E0000, //软件触发方式
0x00000000, //右对齐
disable, //不使用DMA
disable, //单次转换
1 //1个通道
};
void Adc1_Chan1_Init()
{
RCC->APB2ENR |= 1 << 9; //开启ADC1时钟
RCC->APB2ENR |= 1 << 2; //开启GPIOA时钟
GPIOA->CRL &= ~(0xf << 4); //模拟输入
RCC->APB2RSTR |= 1<<9; // ADC时钟复位
RCC->APB2RSTR &= ~(1<<9);
RCC->CFGR &= 0x0000C000; //ADC_APB2 6分频 72M/6 = 12M
RCC->CFGR |= 0x00008000;
ADC1->CR1 = 0x00F0FFFF;
ADC1->CR1 |= ADC_STRUCTInit.ADC_ModeSel << 16; //独立模式
ADC1->CR1 |= ADC_STRUCTInit.ADC_ScanModeSel << 8; //关闭扫描模式
ADC1->CR2 |= ADC_STRUCTInit.ADC_ExternalTrigConv | //软件触发
ADC_STRUCTInit.ADC_DatdAlign | //右对齐
ADC_STRUCTInit.ADC_DMAEN << 8 | // 不使用DMA ADC_STRUCTInit.ADC_ContinuousCon <<1; //单次转换
ADC1->CR2 |= 1 << 20; //使用外部事件启动转换(必须,这里也郁闷了半天)
ADC1->SMPR2 |= 3 << 3; //采样时间,
ADC1->CR2 |= 0x1; //开启ADC (数据手册写错了,必须在校准之前开启ADC,害了我郁闷了半天)
ADC1->CR2 |= 1 << 3;
while (ADC1->CR2 & 1<<3); //复位校准
ADC1->CR2 |= 1 << 2;
while (ADC1->CR2 & 1<<2); //AD校准
}
u16 Get_Value(u8 ch)
{
u16 value;
ADC1->SQR3 &= 0xffffffe0; //
ADC1->SQR3 |= ch;
ADC1->CR2 |= 1<<22; // 开启规则转换
while(!(ADC1->SR & 1<<1));//等待转换结束
value = ADC1->DR ; //读取转换值,清零转换结束状态位
return value ;
}
可以连续采集n次,求平均值提高精确度
http://www.chuxue123.com/forum.php?mod=viewthread&tid=9765&highlight=ADC
重学STM32---(五)ADC的更多相关文章
- STM32之ADC+步骤小技巧(英文)
神通广大的各位互联网的网友们.大家早上中午晚上好好好.今早起来很准时的收到了两条10086的扣月租的信息.心痛不已.怀着这心情.又开始了STM32的研究.早上做了计算机控制的PID实验,又让我想起了飞 ...
- 重学前端 --- Promise里的代码为什么比setTimeout先执行?
首先通过一段代码进入讨论的主题 var r = new Promise(function(resolve, reject){ console.log("a"); resolve() ...
- 重学js之JavaScript 面向对象的程序设计(创建对象)
注意: 本文章为 <重学js之JavaScript高级程序设计>系列第五章[JavaScript引用类型]. 关于<重学js之JavaScript高级程序设计>是重新回顾js基 ...
- 打算写一个《重学Node.js》系列,希望大家多多支持
先放上链接吧,项目已经开始2周了:https://github.com/hellozhangran/happy-egg-server 想法 现在是2019年11月24日,还有人要开始学习Node.js ...
- 重学 Java 设计模式:实战抽象工厂模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 重学 Java 设计模式:实战单例模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 5个创建型模式的最后一个 在设计模式中按照不同的处理方式共包含三大类:创建型模式.结 ...
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)
作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么你的代码那么多ifelse 同类的业务.同样的功能, ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
随机推荐
- NetworkComms网络通信框架V3结构图
NetworkComms网络通信框架序言 来自英国的c#网络通信框架,历时五年打造,由英国剑桥的2位工程师倾情开发,最新版本V3.x版本.
- Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
为了适应各种屏幕尺寸,iOS 6后引入了自动布局(Auto Layout)的概念,通过使用各种 Constraint(约束)来实现页面自适应弹性布局. 在 StoryBoard 中使用约束实现自动布局 ...
- 最新电Call记录统计-full hash join用法
declare @time datetime set @time='2016-07-01' --最新的电Call记录统计查询--SELECT t.zuoxi1,t.PhoneCount,t.Phone ...
- 如何理解java中的变量和常量
int a =10;这是一个变量,在后面的代码中你可以去更改a的值但如果你在声明a的时候加上了final,那么a就成了常量,后面的代码是不允许对a做修改的.还有一点你要注意,被final修饰的常量必须 ...
- jsp作用域
1.page: JSP页面内所有实例的默认作用域都是page,仅限于本页面使用 2.request: 同一次请求所涉及的服务器资源(可能是页面.Servlet等),例如,程序使用<jsp:for ...
- WCF中常见的几种Host,承载WCF服务的方法
1:写在前面 我们都知道WCF在运行的时候必须自己提供宿主来承载服务.WCF 本身没有附带宿主,而是提供了一个 ServiceHost 的类,该类允许您在自己的应用程序中host WCF 服务.然后调 ...
- bzoj 3687 bitset的运用
题目大意: 小呆开始研究集合论了,他提出了关于一个数集四个问题:1. 子集的异或和的算术和.2. 子集的异或和的异或和.3. 子集的算术和的算术和.4. 子集的算术和的异或和.目前为止,小呆已经解决了 ...
- RPI学习--wiringPi_setups
reference: http://wiringpi.com/reference/setup/ There are four ways to initialise wiringPi. wiringPi ...
- 实现viewpager下的圆点滑动
在Drawable目录下创建资源文件 使用shape标签画出背景圆点与当前圆点 背景圆点: <?xml version="1.0" encoding="utf-8& ...
- Servlet三种实现方法(四)
开发Servlet有三种方式:1.实现Servlet接口2.通过继承GenericServlet3.通过继承HttpServlet 一.实现Servlet接口 需求如下:请使用实现 接口的方式,来开发 ...