重学STM32---(五)ADC

发布者:CrystalClear最新更新时间:2025-01-24 来源: cnblogs关键字: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次,求平均值提高精确度


关键字:STM32  ADC  寄存器版 引用地址:重学STM32---(五)ADC

上一篇:重学STM32---(六)DAC+DMA+TIM
下一篇:重学STM32---(四)

推荐阅读最新更新时间:2026-03-19 11:56

STM32复位来源(寄存器
最近项目遇到了一个问题:一个子系统,具有IAP升级的功能,Bootloader位于0x08000000,也就是说系统在运行过程允许复位。但是,该子系统需要在上电的过程中处理某项任务(而且只需要上电的那一次)。 问题来了:我们如何判断系统是第一次上电复位? 解决的办法有很多种,但是最简单的办法就是获取系统复位来源,详情请看文章。 其实,这篇文章的内容也能回答之前一位网友的问题,不知你会不会阅读本文。 Ⅰ RCC复位和时钟控制 RCC:Reset and Clock Control 相信大家都知道RCC是什么,主要就是讲述复位和时钟的章节。先来讲述一下复位种类。 STM32的复位大概分为三类:系统复位、电源复位和后备域复位。 系统
[单片机]
<font color='red'>STM32</font>复位来源(<font color='red'>寄存器</font><font color='red'>版</font>)
STM32入门学习之GPIO(STM32F030F4P6基于CooCox IDE)(寄存器操作
依然,直接上代码 #include stm32f0xx.h #include stm32_lib/inc/stm32f0xx_rcc.h #include stm32_lib/inc/stm32f0xx_gpio.h int main(void) { //IOPAEN=1,使能GPIOA的时钟 RCC- AHBENR |= RCC_AHBENR_GPIOAEN; //设置IO口工作模式,GPIOA_MODER4=0x01,通用IO口 GPIOA- MODER |= GPIO_MODER_MODER4_0; GPIOA- MODER &= ~GPIO_MODER_MODER4_1; /
[单片机]
<font color='red'>STM32</font>入门学习之GPIO(STM32F030F4P6基于CooCox IDE)(<font color='red'>寄存器</font>操作<font color='red'>版</font>
一篇很简单,有必要了解的文章 - STM32复位来源(寄存器
最近项目遇到了一个问题:一个子系统,具有IAP升级的功能,Bootloader位于0x08000000,也就是说系统在运行过程允许复位。但是,该子系统需要在上电的过程中处理某项任务(而且只需要上电的那一次)。 问题来了:我们如何判断系统是第一次上电复位? 解决的办法有很多种,但是最简单的办法就是获取系统复位来源,详情请看文章。 其实,这篇文章的内容也能回答之前一位网友的问题,不知你会不会阅读本文。 Ⅰ RCC复位和时钟控制 RCC:Reset and Clock Control 相信大家都知道RCC是什么,主要就是讲述复位和时钟的章节。先来讲述一下复位种类。 STM32的复位大概分为三类:系统复
[单片机]
一篇很简单,有必要了解的文章 - <font color='red'>STM32</font>复位来源(<font color='red'>寄存器</font><font color='red'>版</font>)
stm32定时器(基本定时器)操作寄存器
定时器本质 定时器的本质:计数器 定时器的构成:时钟源+计数器+重载值 1、stm32的定时器 stm32定时器数量较多、功能比较强;不同的定时器功能有不同。 stm32的定时器进行类型划分。分为三类:①基本定时器;②通用定时器;③高级定时器 基本定时器:用于定时器,还可以用于触发DAC(数模转换器)、ADC(模数转换器)工作。 通用定时器:具备基本定时器所有的功能;捕获输入、比较输出、捕获PWM波、生成PWM波、支持霍尔元件 高级定时器:具备通用定时器所有的功能:支持死区、刹车功能。 STM32F407的基本定时器有TIM6、TIM7. STM32F407的通用定时器有TIM2~TI
[单片机]
<font color='red'>stm32</font>定时器(基本定时器)操作<font color='red'>寄存器</font><font color='red'>版</font>
单片机快速将库函数代码移植为寄存器代码方法
  现在单片机开发越来越多用的是库函数版本的,寄存器版本使用越来越少了。但是在有些项目中使用库函数会导致程序运行速度比较慢,没有直接操作寄存器运行起来速度快。所以在对时间要求比较严格的项目中,还是需要使用寄存器来开发。如果不能够找到寄存器相关示例代码的时候,开发起来还是比较困难的。今天就来总结一个快速将库函数移植为寄存器的方法,这个方式为通用方法,在任何单片机上都可以使用。   现在就用一个STM8单片机库函数的工程来举例。   这个代码的主要功能就是使用定时器1的捕获功能来计算输入波形的频率。对于定时器的初始化使用的都是库函数,现在要将定时器初始化部分的库函数修改为寄存器。   首先单步调试,进入初始化函数中。
[单片机]
单片机快速将库函数<font color='red'>版</font>代码移植为<font color='red'>寄存器</font>代码方法
ULN2003驱动28BYJ-48步进电机STM32F103寄存器
电机1先逆时针旋转90度,再顺时针旋转90度。电机2逆时针旋转90度,再顺时针旋转90度 ◆硬件资源: 1,ULN2003驱动模块 2,28BYJ-48步进电机电机1: // IN4: PC9 d // IN3: PC8 c // IN2: PC7 b // IN1: PC6 a 3,28BYJ-48步进电机电机2: // IN4: PD11 d // IN3: PD10 c // IN2: PD9 b // IN1: PD8 a 单片机源程序如下: #include bjdj.h #include delay.h #define uint unsign
[单片机]
【stm32f103】USART RX实现(寄存器
本讲主要实现usart RX的实现,主要分几部分的应用 1.USART 1 RX polling的实现 2.USART1 RX DMA的实现 3.USART1 RX DMA中断的实现 4.配合着TIMER进行RX DMA中断实现实现(用途很大) 本文章不在对寄存器贴图,直接上代码以及运行图,有兴趣的可以去调试下看看寄存器,以下历程都必须调用Init函数,Init函数源码 void USART1_Init() { /* 1. ENABLE USART1 GPIOA CLOCK */ RCC- APB2ENR |= RCC_APB2ENR_IOPAEN; /* 2. ENABLE USART1 IN A
[单片机]
【stm32f103】USART RX实现(<font color='red'>寄存器</font><font color='red'>版</font>)
第6章 新建工程-寄存器—零死角玩转STM32-F429系列
本章内容所涉及的软件只供教学使用,不得用于商业用途。个人或公司因商业用途导致的法律责任,后果自负。 版本说明:MDK5.15 版本号可从MDK软件的 Help-- About uVision 选项中查询到。 6.1 新建工程 6.1.1 新建本地工程文件夹 为了工程目录更加清晰,我们在本地电脑上新建1个文件夹用于存放整个工程,如命名为 LED ,然后在该目录下新建2个文件夹,具体如下: 表格 8 工程目录文件夹清单 存放编译产生的调试信息、hex文件、预览信息、封装库等 图 61 工程文件夹目录 在本地新建好文件夹后,在文件夹下新建一些文件: 表格 9 工程目录文件夹内容清单 6.1.2 新建
[单片机]
第6章 新建工程-<font color='red'>寄存器</font><font color='red'>版</font>—零死角玩转STM32-F429系列
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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