历史上的今天

今天是:2024年09月17日(星期二)

2021年09月17日 | STM8 ADC转换模式-------连续扫描模式

发布者:码农闲散人 来源: eefocus关键字:STM8  ADC 手机看文章 扫描二维码
随时随地手机看文章

       STM8单片机ADC支持5种转换模式:单次模式,连续模式,带缓存的连续模式,单次扫描模式,连续扫描模式。


      连续扫描模式

        该模式和单次扫描模式相近,只是每一次在最后通道转换完成时,一次新的从通道0到通道n扫描转换会自动开始。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。


        连续扫描模式是在当SCAN位和CONT位已被置时,通过置位ADON位来启动的。

        在转换序列正在进行过程中不要清零SCAN位。

        连续扫描模式可以通过清零ADON位来立即停止。另外一种选择就是当转换过程中清除CONT位那么转换会在下一次的最后一个通道转换完成时停止。


       注意:在扫描模式中,不要使用位操作指令 (BRES) 去清除 EOC 标志位,这是因为该指令是对整个ADC_CSR 寄存器的一个读 - 修改 - 写操作。从 CH[3:0] 寄存器中读取当前的通道编号和写回器,将会改变扫描系列的最后通道编号。


       在连续扫描模式中正确的清除 EOC 标志位的方法是从一个 RAM 变量中载入一个字节到ADC_CSR寄存器,这样来清除EOC 标志位同时还重新载入扫描系列新的最后通道编号。


     读取转换结果的时候可以通过查询方式,也可以通过中断的方式,


     连续扫描模式通过查询方式读取数据代码:


#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 开启扫描模式

 

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

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

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

}

/*

注意:在扫描模式(连续扫描模式)中,不要使用位操作指令(BRES)去清除EOC标志位,

这是因为该指令是对整个ADC_CSR寄存器的一个读-修改-写操作。

从CH[3:0]寄存器中读取当前的通道编号和写回该寄存器,将会改变扫描系列的最后通道编号。

在连续扫描模式中正确的清除EOC标志位的方法是 个RAM变量中载入一个字节到ADC_CSR寄存器,

这样来清除EOC标志位同时还重新载入扫描系列新的最后通道编号。

实验发现,位操作指令只在连续扫描模式中会清除CH[3:0]寄存器中的值,但并不影响其他值。

因此将ADC_CSR中的值读出,再将CH[3:0]中原来通道号加入进去,最后重新写入ADC_CSR中即可。写法如下:

ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_n);

注:ADC1_CHANNEL_n表示扫描到那个通道结束。

*/

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;             //程序运行一圈耗时 10us    

    

        while( ( ADC_CSR & 0x80 ) == 0 );      //等待转换结束

        //ADC_CSR &= ~( 1 << 7 );               // 不能通过位操作来清零  EOC 标志

        

        ADC_CSR = ADC_CSR & 0x7F | 0x04;        // 转换结束标志位清零  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;

    }

    return voltage;

}

 

   连续扫描模式通过中断方式读取数据代码:


#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 并开始转换

}

 

 

/*

注意:在扫描模式(连续扫描模式)中,不要使用位操作指令(BRES)去清除EOC标志位,

这是因为该指令是对整个ADC_CSR寄存器的一个读-修改-写操作。

从CH[3:0]寄存器中读取当前的通道编号和写回该寄存器,将会改变扫描系列的最后通道编号。

在连续扫描模式中正确的清除EOC标志位的方法是 个RAM变量中载入一个字节到ADC_CSR寄存器,

这样来清除EOC标志位同时还重新载入扫描系列新的最后通道编号。

实验发现,位操作指令只在连续扫描模式中会清除CH[3:0]寄存器中的值,但并不影响其他值。

因此将ADC_CSR中的值读出,再将CH[3:0]中原来通道号加入进去,最后重新写入ADC_CSR中即可。写法如下:

ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_n);

注:ADC1_CHANNEL_n表示扫描到那个通道结束。

*/

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

u16 temph = 0;

u8 templ = 0;

 

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

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

__interrupt void ADC_Handle( void )

{

 

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

    

    //ADC_CSR &= ~( 1 << 7 );               // 不能通过位操作来清零  EOC 标志

    ADC_CSR = ADC_CSR & 0x7F | 0x04;        // 转换结束标志位清零  EOC

 

    //单通道扫描模式,转换结果存储在 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_flag = 1;                       // ADC中断标志 置1

}


关键字:STM8  ADC 引用地址:STM8 ADC转换模式-------连续扫描模式

上一篇:STM8输出PWM变频时波形断开解决方法
下一篇:STM8 ADC转换模式-------单次扫描模式

推荐阅读

   时间进入到9月,我们这几天已经明显感觉到早晚的天气逐渐变冷,气温上来看,秋天正在离我们越来越近。秋天是个收获的季节,而在十一还能赶上一个黄金周,这个时候三五个好友一起出游是个不错的选择。出游拍照留念当然是不可避免的,那么相机就是必不可少的了。如果您不愿意背着很沉的单反,喜欢手机拍照分享的乐趣,不妨参考下这篇文章,下面新浪手...
《电工学》或者《电路分析》教材中,对电容的定义是这样的,如图(01),满足图(01)式的电路元件,就是电容。式中i和u都是时间t的函数,电容量C是常数。图(01)  我们把dt移到左边,如图(02)。图(02)  两边对时间积分,积分限从0到t。因为电容量C为常数,所以可提到积分号之外。图(03)  我们来看看左边的积分结果和右边的积分结果是什么意思。  左边...
Jayanth Rangaraju目前担任德州仪器(TI)的系统经理,致力于可再生能源。在此职位,他的团队负责利用TI的产品组合来利用系统解决方案和专业知识来解决工程问题。在德州仪器的13年中,Jayanth担任过各种职务,包括设计工程师、应用程序和系统经理以及市场经理。他获得了德克萨斯大学阿灵顿分校电气工程硕士学位。他于2015年毕业于德克萨斯大学奥斯汀分校...
步进电机具有结构简单、易于控制、安全性高、成本低、转矩高等优点,作为一种高性能的数字化电气元件,广泛应用于各种类型的开环控制系统中。然而,步进电机有一个缺点,在简单的开环设计中,它可以在低速产生噪声。噪声和共振主要来源于驱动电路和机械结构的共振。噪声可能是任何电气设备的问题,从变压器到直流电机,工业界一直在寻找经济的方法来降低发...

史海拾趣

问答坊 | AI 解惑

陶瓷电容器的应用

陶瓷电容器的应用…

查看全部问答∨

一个奇怪的现象

(线性稳压电源)  通过全桥整流后接电容   如果接的电阻比较小  也即取出的电流大   此时时间常数会变小   我用示波器测试发现输出时降低了   但是按照电容充放电原则    ...…

查看全部问答∨

请大家推荐一款易于上手的USB开发芯片

初学,想做点小玩意儿,请大家推荐一款易于上手的USB开发芯片.谢谢…

查看全部问答∨

关于超时的定义

我最近在学UART通信。用得书是《深入浅出ARM7》。在用中断方式通信里书上只给了RDA中断的例子。我想写一个可以循环接受到任意长度字符的程序,也就是说,不管到没到触发值,所被发的字符都能被接受到。我是不是只要加一个溢出中断和字符超时中断就 ...…

查看全部问答∨

激光测距仪

我是用激光测距仪获得一些数据后,怎么能用什么软降将其成像,请帮帮忙…

查看全部问答∨

急:关于ISA GUID?

{0x4ec507d3, 0xfbe2, 0x4c4d, { 0xa5, 0…

查看全部问答∨

要看懂原理图需要哪些基础?

看懂原理图需要哪些学科的知识作为基础啊? 数电模电没学能不能看懂图呢? …

查看全部问答∨

QUARTUS2编译出错误了

用quartus 2编译一下程序:LIBRARY ieee;USE ieee.std_logic_1164.ALL;ENTITY seg7dec IS   PORT(bcdin : IN std_logic_vector(3 DOWNTO 0);        segout : OUT std_logic_vector(6 DOWNTO 0));END seg7 ...…

查看全部问答∨

公司组织技能比赛

       公司组织个技能比赛,从简单的机械加工到电器修理机械制图等,总之就是和我们平时工作息息相关的工作一些比赛!       设置不同的奖励,交个底就是只要能选上你就有现金奖励, ...…

查看全部问答∨

STM8中断向量表,有哪位朋友详细描述一下。

例如: 1、_stext是什么意思?           2、这个地址可能改吗?如果程序里有BOOTLOADER是不是要改。           3、typedef void @far (*interrupt_handler_t)(void);是什么意 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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