STM8单片机ADC单次扫描模式

发布者:红尘清梦最新更新时间:2021-09-16 来源: eefocus关键字:STM8  单片机  ADC 手机看文章 扫描二维码
随时随地手机看文章

  当STM8单片机使用ADC功能读取多个通道的值时,可以使用单次模式,采样完一个通道之后,重新初始化另一个通道,然后采样,采样完成后继续重新初始化切换下一个通道。但是这样采样起来太麻烦。STM8单片机提供了一个扫描模式,可以依次按照顺序采样多个通道的值,多个通道全部采样完成后,会置位标志位,这样就可以一次性将多个通道的值全部读出来。


  其中官方文档介绍如下:

image.png

  从文档中可以看出,采样都是从0通道开始的,比如想采样3个通道值,那么采样的通道号就为0—3。如果想采样3、4通道,那么也得从0通道开始,也就是说要从0通道开始扫描到4通道,就算0、1、2通道不用,它也会扫描,就这一点不好。

image.png

  单次采样的时候,ADC_CSR寄存器中的通道号指的是要采样的通道号,要采样那个通道就设置为几,而在扫描模式下,这个通道号指的是要扫描的最大通道号,扫描都是从0通道开始。这里设置时要注意。


  单次扫描模式的配置其实也很简单,只是比单次模式多了一个开启扫描的设置。下面直接通过寄存器来说明单次扫描模式的设置方法。

image.png

  首先看ADC_CSR寄存器,这个寄存器里面只需要设置一个通道转换位,这个通道指的是扫描的最大通道。在单次模式下这个通道指的是要读取的通道值,而在扫描模式下,这个通道指的是,最大扫描通道数。扫描都是从0通道开始。EOC位是转换结束标志位,这个在初始化的时候不用设置,只是在读取数据的时候通道判断这个位来读取。

image.png

  接下来看ADC_CR1寄存器,这个寄存器要设置的只有一个,就是ADON位,用来控制ADC的转换开关,为1时启动转换功能,为0时关闭转换功能。预分频位和单次转换模式默认值都为0,刚好符合我们的需求,也就是默认2分频,单次转换模式。

image.png

  接下来看ADC_CR2寄存器,这个寄存器必须设置的位其实只有一个,就是要要使用扫描模式必须设置SCAN位为1,其他位使用默认值就行。如果数据对齐方式使用左对齐的话,就不用设置。这里使用的是数据右对齐,所以需要将ALIGN位也设置为1.其他位默认为0.

image.png

  最后就是这个ADC_TDR寄存器,用来禁止施密特触发器,主要是用来降低单片机功耗。当然这个寄存器不用设置也可以。如果要设置的话,使用了哪几个ADC通道,就将对应的通道位置1就行。


  下面就可以开始编写代码了:


#include "adc.h"

#include "main.h"

#include "led.h"


_Bool ADC_flag = 0;                     //ADC转换成功标志

u16 ADC_DB[10] = {0};

u16 adc_data[5] = {0};


//AD通道引脚初始化

void ADC_GPIO_Init( void )

{

    PD_DDR &= ~( 1 << 2 );              //PD2 设置为输入

    PD_CR1 &= ~( 1 << 2 );              //PD2 设置为悬空输入


    PD_DDR &= ~( 1 << 3 );              //PD3 设置为输入

    PD_CR1 &= ~( 1 << 3 );              //PD3 设置为悬空输入


    PC_DDR &= ~( 1 << 4 );              //PC4 设置为输入

    PC_CR1 &= ~( 1 << 4 );              //PC4设置为悬空输入

}


//设置为 单次扫描模式

//ch 为ADC通道 连续转换AIN0---AINch 通道的数据

void ADC_CH_Init( u8 ch )

{

    char l = 0;

    ADC_GPIO_Init();    

    ADC_CR1 &= ~( 7 << 4 );   //预分频 2

    ADC_CR2 &= ~( 1 << 6 );   //不使用外部触发

    //禁止 AIN2 AIN4 的施密特触发器,降低 IO 静态功耗  PD5,PD6 上的通道如果施密特方式禁用会导致串口无法收发数据!

    ADC_TDRL |= ( 1 << 2 );

    ADC_TDRL |= ( 1 << 3 );

    ADC_TDRL |= ( 1 << 4 );


    ADC_CR1 &= ~( 1 << 1 );   //单次转换

    ADC_CSR |= 0x04;          //配置通道号最大的那个

    ADC_CR2 |= ( 1 << 3 );    //右对齐


    ADC_CR1 |= ( 1 << 0 );    //开启 ADC

    ADC_CR2 |= ( 1 << 1 );    // SCAN = 1 开启扫描模式


    //当首次置位ADON位时,ADC从低功耗模式唤醒。为了启动转换必须第二次使用写指令来置位ADC_CR1寄存器的ADON位。

    for( l = 0; l < 10; l++ );  //延时,保证ADC模块的上电完成 至少7us

    ADC_CR1 |= ( 1 << 0 );      //再次将CR1寄存器的最低位置1 使能ADC 并开始转换

}


u16 ain2_val = 0,ain3_val = 0,ain4_val = 0;

//读取采样电压值

u16 ReadVol_CHx( void )

{

    u16 voltage = 0;

    u16 temph = 0;

    u8 templ = 0;

    while( 1 )

    {

        LED = !LED;             //程序运行一圈耗时 15us           

        while( ( ADC_CSR & 0x80 ) == 0 );      //等待转换结束  等待时间为 4us

        ADC_CSR &= ~( 1 << 7 );               // 转换结束标志位清零  EOC


        //读取 AIN2 的值

        templ = ADC_DB2RL;

        temph = ADC_DB2RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain2_val =  temph;

        

        //读取 AIN3 的值

        templ = ADC_DB3RL;

        temph = ADC_DB3RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain3_val =  temph;


        //读取 AIN4 的值

        templ = ADC_DB4RL;

        temph = ADC_DB4RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain4_val =  temph;

        

        ADC_CR1 |= 0x01;                        //开启一次转换

    }

    return voltage;

}


  初始化流程就按照上面分析的流程进行,在启动ADC转换的时候,需要开启两次。

image.png

  系统启动后ADC默认是在低功耗模式下,第一次设置ADON位是将ADC从低功耗模式唤醒,然后需要延时1个转换周期,等待系统转换稳定。所以在初始化的时候需要设置两次ADON为1。由于这里使用的是单次触发模式,所以每次转换完成之后,ADC默认就关闭了,如果要继续转换,就需要手动将ADON位设置为1.


  也可以使用中断的方式来进行读取数据。


#include "adc.h"

#include "main.h"

#include "led.h"


_Bool ADC_flag = 0;                     //ADC转换成功标志


u16 ADC_DB[10] = {0};

u16 adc_data[5] = {0};


//AD通道引脚初始化

void ADC_GPIO_Init( void )

{

    PD_DDR &= ~( 1 << 2 );              //PD2 设置为输入

    PD_CR1 &= ~( 1 << 2 );              //PD2 设置为悬空输入


    PD_DDR &= ~( 1 << 3 );              //PD3 设置为输入

    PD_CR1 &= ~( 1 << 3 );              //PD3 设置为悬空输入


    PC_DDR &= ~( 1 << 4 );              //PC4 设置为输入

    PC_CR1 &= ~( 1 << 4 );              //PC4设置为悬空输入

}


//设置为 单次扫描模式

//ch 为ADC通道 连续转换AIN0---AINch 通道的数据

void ADC_CH_Init( u8 ch )

{

    char l = 0;

    ADC_GPIO_Init();


    ADC_CR1 &= ~( 7 << 4 );   //预分频 2

    ADC_CR2 &= ~( 1 << 6 );   //不使用外部触发

    //禁止 AIN2 AIN4 的施密特触发器,降低 IO 静态功耗  PD5,PD6 上的通道如果施密特方式禁用会导致串口无法收发数据!

    ADC_TDRL |= ( 1 << 2 );

    ADC_TDRL |= ( 1 << 4 );


    ADC_CR1 &= ~( 1 << 1 );   //单次转换

    ADC_CSR |= 0x04;          //配置通道号最大的那个

    ADC_CR2 |= ( 1 << 3 );    //右对齐


    ADC_CR1 |= ( 1 << 0 );    //开启 ADC

    ADC_CR2 |= ( 1 << 1 );    // SCAN = 1 开启扫描模式


    ADC_CSR |= ( 1 << 5 );    //EOCIE 使能转换结束中断


    //当首次置位ADON位时,ADC从低功耗模式唤醒。为了启动转换必须第二次使用写指令来置位ADC_CR1寄存器的ADON位。

    for( l = 0; l < 10; l++ );  //延时,保证ADC模块的上电完成 至少7us

    ADC_CR1 |= ( 1 << 0 );      //再次将CR1寄存器的最低位置1 使能ADC 并开始转换


}

u16 ain2_val = 0, ain3_val = 0, ain4_val = 0;

u16 temph = 0;

u8 templ = 0;

//读取采样电压值

u16 ReadVol_CHx( void )

{

    u16 voltage = 0;

    if( ADC_flag == 1 )

    {

        ADC_flag = 0;

        //单通道扫描模式,转换结果存储在 ADC_DBxR 寄存器中

        //读取 AIN2 的值

        templ = ADC_DB2RL;

        temph = ADC_DB2RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain2_val =  temph;


        //读取 AIN3 的值

        templ = ADC_DB3RL;

        temph = ADC_DB3RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain3_val =  temph;


        //读取 AIN4 的值

        templ = ADC_DB4RL;

        temph = ADC_DB4RH;

        temph = ( u16 )( templ | ( u16 )( temph << ( u16 )8 ) );

        ain4_val =  temph;


        ADC_CR1 |= 0x01;                        //开启一次转换

    }

    return voltage;

}

//AD中断服务函数 中断号22

#pragma vector = 24                     // IAR中的中断号,要在STVD中的中断号上加2

__interrupt void ADC_Handle( void )

{

    ADC_CSR &= ~( 1 << 7 );               // 转换结束标志位清零  EOC

    ADC_flag = 1;                       // ADC中断标志 置1

}


  中断的开启就是将ADC_CSR寄存器的EOCIE位设置为1,然后当所有的通道转换完成之后,就会产生一次中断,在中断中读取数据。


  这里要注意的地方是在扫描模式时,采样的数据结果不是存放在ADC_DR寄存器中,而是存放在ADC_DBxR寄存器中,通道几就存放在对应的ADC_DBxR寄存器中,这个寄存器分为高位和低位两个。比如通道2的数据,就存放在ADC_DB2RL和ADC_DB2RH寄存器中,在读取数据的时候也要注意,如果数据是左对齐必须先读高8位,再读低位。如果数据是右对齐必须先读低8位,在读高8位。

image.png

image.png

  数据对齐在官方手册中有详细的说明,在使用的时候要注意这一点。


关键字:STM8  单片机  ADC 引用地址:STM8单片机ADC单次扫描模式

上一篇:STM8单片机ADC连续扫描模式
下一篇:STM8单片机ADC带缓存的连续采样模式

推荐阅读最新更新时间:2024-11-09 10:46

stm32 嵌入式开发 中三重ADC交替模式采集数据总结
// ADC 宏定义 #ifndef __BSP_ADC_H #define __BSP_ADC_H #include stm32f4xx.h // ADC GPIO 宏定义 #define RHEOSTAT_ADC_GPIO_PORT GPIOC #define RHEOSTAT_ADC_GPIO_PIN GPIO_Pin_3 #define RHEOSTAT_ADC_GPIO_CLK RCC_AHB1Periph_GPIOC // ADC 序号宏定义 #define RHEOSTAT_ADC1 ADC1 #define RHEOSTAT_ADC1_CLK RCC_APB2Peri
[单片机]
stm32 嵌入式开发 中三重<font color='red'>ADC</font>交替<font color='red'>模式</font>采集数据总结
STM32单片机的调试方式 STM32单片机的启动流程详解
STM32单片机是意法半导体推出的一款基于ARM Cortex-M内核的32位微控制器,广泛应用于汽车电子、工业控制、消费电子等领域。 STM32单片机的调试方式: 1.使用JTAG调试器:JTAG调试器是一种常用的调试工具,可以用于单步执行、断点调试等操作。在STM32单片机中,可以使用ST-Link、STMicroelectronics IDE等工具进行JTAG调试。 2.使用串口调试器:串口调试器可以通过串口与单片机进行通信,实现单步执行、断点调试等功能。在STM32单片机中,可以使用ST-Link、STMicroelectronics IDE等工具进行串口调试。 3.使用仿真器:STM32单片机可以使用仿真器进行开发和
[单片机]
STC89C52单片机实验1-点亮一个发光二极管
/*-------------------------------------------------------------------------- REG51.H Header file for generic 80C51 and 80C31 microcontroller. Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifnde
[单片机]
关于恩智浦lpc824 和lpc84x 微控制器
随着物联网技术的发展,MCU 处理器的能力日益强大,如今的MCU 与微处理器的界线越来越模糊,将会进一步融合成为嵌入式处理器。由于AMetal 已经完全屏蔽了底层的复杂细节,因此开发者仅需了解MCU 的基本功能就可以了。 LPC82x 是一款基于 ARM Cortex-M0+ 的低成本 32 位 MCU 系列器件(主芯片LPC824,基于ARM® Cortex®-M0+内核的低成本微控制器(MCU)),工作时 CPU 频率高达 30 MHz。 LPC82x 支持最高32 KB 闪存和 8 KB SRAM。LPC82x 的配套外设包括一个 CRC 引擎、四个 I2C 总线接口、最多三个 USART、最多两个 SPI 接口、一个多速
[单片机]
关于恩智浦lpc824 和lpc84x <font color='red'>微控制器</font>
基于89C51时钟电路的设计与制作
随着电子技术的飞速发展,单片机的使用率越来越高。教学之余,为了激发学生对51单片机的学习兴趣,我利用89C51制作了一款电子时钟,经验证这款电子时钟简单实用,以至于班上的每个同学都制作一款。由于51系列单片机机展小巧、程序编写简、功能强大、价格便宜等优点,由51单片机制作的小型智能产品越来越多,也是电子技术相关专业学生毕业设计的首选芯片(见图1)。 1 电路设计流程框图(见图2) 2 基于89C51时钟电路的方案及原理 基于89C51时钟电路主要由主要由微处理器电路、LED数码管显示电路、键盘电路、显示驱动电路、时钟模块、电源电路等组成。89C51的管脚及技术细节可以查阅有关手册。电路模块的基本工作过程是: (1)显示
[单片机]
基于89C51时钟电路的设计与制作
一种微型生态花园控制系统设计
摘 要: 以STM32F407ZGT6单片机为核心控制器设计了一种微型生态花园控制系统,将传感器技术、Wi-Fi技术、摄像头技术、自动追光技术、μC/OS-Ⅲ实时操作系统结合起来,实现对花园环境以及动植物情况的实时监控和及时控制,并具有环境温度、环境湿度、土壤湿度、光照强度监控,鱼缸自动换水、增氧以及宠物自动喂养等功能。 0 引言 随着城市生活节奏越来越快,都市白领人群也越来越多地希望绿色微生态能够进入自己的家庭阳台空间,开始更多地从生态角度改善自己的生活环境。 当前物联网技术的应用,使得生态空间的控制技术朝人工智能化方向迅速发展 。新技术的应用使得微生态阳台花园的管理通过智能自动化系统实现了实时控制,代替了原有落后的开关
[单片机]
一种微型生态花园控制系统设计
单片机iic通信的工作原理简述
单片机IIC通信是指在单片机控制下,通过IIC总线进行的数据传输和通信。IIC通信是一种串行通信方式,通过SCL和SDA两个线路进行数据传输,SCL线路是时钟线,SDA线路是数据线。IIC通信协议采用主从式通信,主设备发出请求,从设备响应请求,从设备返回数据,主设备接收数据,通信过程中主从设备的角色可以互换。 IIC通信分为两种模式:传输模式和寄存器访问模式,其中传输模式是指数据的传输,寄存器访问模式是指对设备的寄存器进行读写操作。在传输模式中,主设备发出开始信号,从设备接收到开始信号后,开始等待数据的接收。主设备发送数据时,从设备按位接收数据,接收完数据后,从设备发送应答信号。主设备接收到应答信号后,继续发送数据,直到发送完
[单片机]
<font color='red'>单片机</font>iic通信的工作原理简述
51单片机可以做什么实用的产品?
我用51的单片机做过不少于10款产品了。 我看到很多文章,说51已经过时了,新手没必要学习51单片机,可以直接学STM32。 我个人认为这种说法存在一定的误导, 51还是有很大的市场 。 很多人想从事嵌入式单片机开发,觉得这个行业会随着物联网和5G等技术的发展,前景越来越好。 但是又不知道从哪里入手,该学习哪个单片机,别人都说现在主流是用STM32,你就随波逐流去学习STM32。 但是却 忽略了一个很重要的前提,就是你的基础 。 每个人的基础都不一样,很多人没什么学历,也是从别的行业转过来的,很多连c语言基本语法和电路基础都不懂。 这个时候去学习stm32属于跨级打怪了,能学会学好才怪。 这就是为什么我们无际单片机编程对每个新加入
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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