STM8单片机ADC采样功能通过定时器触发

发布者:丹青妙手最新更新时间:2022-01-15 来源: eefocus关键字:STM8  单片机  定时器触发 手机看文章 扫描二维码
随时随地手机看文章

  在使用STM8单片机的ADC功能时,读取ADC数据时一般有两种方式,一种是通常不断地读取采样标志位,来判断ADC采样是否结束,一种是通过中断的方式来通知系统采样是否结束。


  有时候采样ADC数据的时候,需要按照一定的时间间隔,定点的去采样数据。一般使用的方式就是通过定时器定时,然后在定时中断函数中再去读取ADC采样的数据。但是这种方式采样的时间是不固定的,比如进入定时器中断后,ADC采样刚结束,就可以直接使用当前采样到的数据。但是如果运气不好的话,进入定时中断后,ADC采样刚开始,那么此时就需要等到ADC采样结束后,才能使用数据。这样就好导致每次读取ADC数据时还会有随机的一段等到ADC数据的延时。


  通常查阅STM8单片机的手册发现,ADC采样可以通过定时器来触发。

在这里插入图片描述

  通过定时器来触发ADC采样时,定时器的定时时间是固定的,采样时间也是固定的,这样采样数据的间隔也就是固定的。这样通过定时器来触发ADC的采样时间,就能完全保证每次读取ADC采样数据的时间间隔都是一样的,从而避免了数据的误差。


  数据手册中对于开启ADC触发功能描述如下:

在这里插入图片描述

  对于如何通过代码来设置ADC触发,官方也没有详细的说明,在网上也没有找到相关例程。所以只能自己摸索,还好通过自己的一番摸索,成功的通过定时器的TRGO事件触发了ADC的启动。


  关于ADC相关寄存器的设置,基本就是上面说的6条。接下来需要设置的就是定时器的相关寄存器。

在这里插入图片描述

  关于定时器只需要设置CR2寄存器中的 MMS位就可以了。


  接下来就通过代码来实现。


#include "adc.h"

#include "main.h"

#include "led.h"


u16  DATAH = 0;                          //ADC转换值高8位

u16  DATAL = 0;                          //ADC转换值低8位

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


u16 adc_cnt = 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 设置为悬空输入

}

//ch 为单片机的ADC 通道

//ADC输入通道初始化入口参数表示通道选择

void ADC_CH_Init( u8 ch )

{

    char l = 0;

    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz  单次转换,禁止转换

    ADC_CR2  = 0x00;                    //默认左对齐 读数据时先读高在读低

    

    ADC_CR2 |= ( 1 << 6 );              //外部触发使能


    ADC_CSR  |= ch;                     //控制状态寄存器 选择要 AD输入通道  如:PD2(AIN3)

    ADC_TDRL = ( 1 << ch  );            //禁止相应通道 施密特触发功能 1左移ch位

    ADC_CR1 |= 0x01;                    //使能ADC并开始转换

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

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

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

}


u16 value = 0;

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

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

__interrupt void ADC_Handle( void )

{

    ADC_CSR &= ~0x80;                            // 转换结束标志位清零  EOC

    //默认左对齐 读数据时先读高高8位 再读低8位

    DATAH = ADC_DRH;                             // 读出ADC结果的高8位

    DATAL = ADC_DRL;                             // 读出ADC结果的低8位

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

    value = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据  0--1024

    adc_cnt++;

    LED = !LED;

}


  在ADC代码中,相比普通的ADC初始化方式,这里只需要增加一句对ADC_CR2寄存器的设置。


ADC_CR2 |= ( 1 << 6 ); //外部触发使能

在这里插入图片描述

  在ADC_CR2寄存器中 使能外部触发转换功能,设置外部触发事件为 内部定时器1 TRG事件。


  这里ADC使用的是单次触发模式,开启外部触发功能,开启ADC转换中断,当ADC转换完成之后,就会进入到ADC中断中,在中断中读取采样的数据,然后翻转LED的状态,通过示波器观察LED引脚电平的变化,就可以知道ADC中断进入的频率了。


  接下来编写定时器初始化代码。


unsigned long time_cnt = 0;

// 使用 定时器触发 ADC采样

void tim1_init( void )

{

    TIM1_ARRH = ( unsigned char )( 1000 >> 8 );         //定时1ms

    TIM1_ARRL = ( unsigned char )( 1000 );

    TIM1_PSCRH = ( unsigned char )( 0x0F >> 8 );        // 16M / (1+15) =1M

    TIM1_PSCRL = ( unsigned char )( 0x0F );

    TIM1_RCR = 0x00;                                    //重复计数器值

    TIM1_SR1 = ( ~0x01 );                        //清除更新中断标志


    TIM1_CR2 |= ( 2 << 4 );                             //使能信号,用于触发输出(TRGO)

    

    TIM1_CR1 |= 0x01;                                   //使能计数器

    TIM1_IER |= 0x01;                            //更新中断使能

}


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

__interrupt void Timer1_Handle( void )          //1ms 定时中断

{

    TIM1_SR1 = ( ~0x01 );                        //清除更新中断标志

    time_cnt++;

}


  定时器的初始化代码,也比正常情况下初始化代码多了一行。


TIM1_CR2 |= ( 2 << 4 ); //使能信号,用于触发输出(TRGO)


  用来开启定时的的TRG功能。

在这里插入图片描述

  经过测试,这里定时器CR2寄存器中的值 只能设置为 010 或者 011,设置为其他值时,不能触发ADC采样。最开始测试的时候按照芯片资料上这个说明,MMS的值设置的是 001,ADC总是触发不了,还以为是方法的问题,最后才发现是MMS值设置的问题。


  ADC和定时器初始化代码设置完成之后,接下来在主函数中初始化这两个函数就行了,按照资料上说的,首先初始化完ADC之后,再初始化定时器。


void main( void )

{


    __asm( "sim" );                             //禁止中断

    SysClkInit();

    delay_init( 16 );

    LED_GPIO_Init();

     ADC_GPIO_Init();

    ADC_CH_Init(3);

    tim1_init();

    __asm( "rim" );                             //开启中断

    while( 1 )

    {

       

    }

}

  接下来运行程序。

在这里插入图片描述

  分别在ADC中断中和定时器中断中用一个变量来统计中断执行的次数,通过变量变量观察窗口可以看到,ADC中断的次数比定时器中断的次数多了1次。这是因为ADC在初始化的时候,已经运行了一次。


  然后通过示波器观察LED口的电平。

在这里插入图片描述

  定时器的定时时间是1ms,LED的高低电平时间也是1ms,说明通过定时器触发ADC采样功能是正常运行的。


  为了减小系统进入中断的次数,可以将定时器的中断功能关闭掉。定时器中断功能关闭后,ADC的触发功能依然可以正常使用。

在这里插入图片描述

  这样只需要开启一个ADC中断,再加上定时器的TRG触发功能后,就可以实现ADC定时采样的功能了。

关键字:STM8  单片机  定时器触发 引用地址:STM8单片机ADC采样功能通过定时器触发

上一篇:STM8单片机通过PWM触发ADC同步采样
下一篇:单片机快速将库函数版代码移植为寄存器代码方法

推荐阅读最新更新时间:2024-11-12 11:43

Unity+VS2012+CodeWarrior v5.x(MCU为MC9S12XEP100)开发环境配置
前言 这个系列来一期嵌入式TDD实战,讲一下目前我嵌入式TDD开发的整个过程(不包括版本管理部分,虽然实际上我是用VCS来回顾之前的一步一步做了什么的),肯定不是最佳做法,还在不断改进中,算是给想学习类似开发方法的人提供一个实践的参考,入个门。 整个课程(姑且叫做课程吧)的主线就是记录了我通过TDD的方法开发 Flash芯片AT26DF的驱动模块 的整个过程,这个模块的当前版本已经发在之前的博文中:https://blog.csdn.net/lin_strong/article/details/90274561。 我们会从整个项目的基本配置讲起,搭建好开发环境,然后一起翻开芯片的手册,对驱动模块进行构思,构造mock对象;
[单片机]
Unity+VS2012+CodeWarrior v5.x(<font color='red'>MCU</font>为MC9S12XEP100)开发环境配置
KST51单片机:通过中断实现矩阵按键的次数检测与消抖
以Key4为例,使用定时中断2ms进行消抖,对连续8次(16ms)的按键状态进行判断. 如果全部为1则弹起,将按键当前状态(Keysta)为1; 全部为0则按下,将按键当前状态(Keysta)置0; 其余状态都为抖动,按键当前状态不变。 在主程序里对按键状态进行判断,如果按键当前状态(Keysta)与按键历史状态(backup)不同,则说明按键状态发生变化。程序中是弹起时,按键次数改变,将最新的按键次数送给数码管显示,将按键历史状态更新为当前状态并进行下一次判断。源代码如下: #include reg52.h sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2
[单片机]
KST51<font color='red'>单片机</font>:通过中断实现矩阵按键的次数检测与消抖
[单片机框架] main文件的实现和RTX移植
一、 新建工程 选择芯片型号 选择中间件,勾选RTX 选择完毕后,ok解锁。 main文件内容如下,由于我对RTX函数,再封装了一层,是为了方便切换其他OS。 /******************************************************************************** * @file main.c * @author jianqiang.xue * @Version V1.0.0 * @Date 2021-04-03 * @brief 无 ************************************************************
[单片机]
[<font color='red'>单片机</font>框架] main文件的实现和RTX移植
PIC单片机led灯左移右移
程序介绍:每隔100ms,移动一个灯亮 //** Date: Wednesday, November 21, 2012 21:26:32 #define MX_PIC //Defines for microcontroller #define P16F690 #define MX_EE #define MX_EE_SIZE 256 #define MX_SPI #define MX_SPI_BCB #define MX_SPI_SDI 4 #define MX_SPI_SDO 7 #define MX_SPI_SCK 6 #define MX_UART #define MX_UART_B #define
[单片机]
PIC<font color='red'>单片机</font>led灯左移右移
红外遥控系统原理及单片机软件解码程序
首先,必须要了解一些基本原理。其实按下遥控器的某一个键,遥控器会发出一连串经过调制后的信号,这个信号经过红外一体化模块接收后,输出解调后的数字脉冲,每个按键对应不同的脉冲,故识别出不同的脉冲就能识别出不同的按键。 上图就是很常见的车载MP3遥控器,比较小巧,很好用。下面是红外发射和接受原理: 到此读者可能会有疑惑,那么不同的调制解调方法那么出来的脉冲规则是不一样的?是的,的确如此。 遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC的uPD6121G组成发射电路为例说明编码原理(一般家庭用的DVD、VCD、音响都使用这种编码方式)。当发射器按键按下后
[单片机]
红外遥控系统原理及<font color='red'>单片机</font>软件解码程序
单片机学习记录——蜂鸣器
硬件连接 从图中可知,蜂鸣器只有一个接口与外部相连接。我们通过跳线把J8接口与单片机的P0.0接口相连接。 蜂鸣器发声原理 有源蜂鸣器,也称压电式压蜂鸣器,主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。 其中最重要的就是它的压电蜂鸣片,通常这是一种压电陶瓷,能进行电能与机械能的转换。 发声过程为:外部提供恒定直流电压,提供能量给多谐振荡器,多揩振荡器起振,并提供变化的电压和频率给压电陶瓷,压电陶瓷将电能转化为机械能,也就发出了声音。 无源蜂鸣器,也称电磁式蜂鸣器,主要由永磁体,线圈,振荡片构成。 发声过程为:外部按一定频率提供驱动一个振荡信号(一定占空比的方波,该信号作用于线圈,产生的磁声与永
[单片机]
<font color='red'>单片机</font>学习记录——蜂鸣器
51单片机学习:ADC模数转换实验--热敏电阻AD采集
实验名称:ADC模数转换实验--热敏电阻AD采集 接线说明: 实验现象:下载程序后,数码管上显示AD模块采集热敏电阻的AD值 注意事项: ***************************************************************************************/ #include public.h #include smg.h #include xpt2046.h /******************************************************************************* * 函 数 名 : main * 函数功能 : 主
[单片机]
【GD32 MCU 入门教程】二、GD32 MCU 烧录说明(3)脱机烧录
大部分主流的烧录器厂商均支持GD32 MCU的烧录,如ELNEC、致远电子、贷铺科技、希尔特、迈斯威志、轩微、天津威磊、Segger、芯园电子、北极星电子等烧录器厂商。烧录方式分别有SWD和ISP,具体以烧录器型号为准。 GD官方的GD-link烧录工具也支持离线烧录功能,装载好代码后通过按键即可进行脱机烧录,需注意GD-link脱机烧录只能装载768K大小的文件。以下主要介绍GD-link的脱机烧录方法。所需工具和软件:GD-link、官网获取最新版本GD-link Programmer上位机。 3.1 GD-link脱机烧录硬件连接 GD-link脱机烧录的硬件连接方式与在线下载相同,硬件接口和连接方式请参考2.5章节说明
[单片机]
【GD32 <font color='red'>MCU</font> 入门教程】二、GD32 <font color='red'>MCU</font> 烧录说明(3)脱机烧录

推荐帖子

分享一个threadx在linux上的坑
threadx跑在linux上面,起因是当时想把中位机(linux)和单片机的代码统一起来,用一套基础os来覆盖控制端和板卡。看着threadx有linux的port,因此搞上去很畅快。但是问题来了,threadx上用的定时器等本来应该是硬件中断产生的信号,在linuxport上使用的软件定时器+信号signal的方式,SIGUSR1和SIGUSR2,可是大量linux的系统调用都会被中断打断,返回EINT,这让很多休眠等待的系统调用,比如阻塞读,不得不处理EINT中断后的恢复。设置信
freebsder 嵌入式系统
DIY手机+蓝雨夜 材料准备
DIY手机+蓝雨夜材料准备这段时间一直在选择器件。先把需要的元器件准备起来,该买的买,该申请的申请主要器件还是选TI的了!再加上以前论坛里团购的片子先把硬件都考虑进去,程序功能等看时间是否允许在完善吧!DIY手机+蓝雨夜材料准备高大上,TI的样片,口水ing。楼主准备的材料不错,期待大作点歌赞,稍后我也为活动做点贡献看到了:模块,2个屏,蓝牙,电源管理相片芯片等sacq发表于2014-5-3014:38看到了:模块,2个屏,蓝牙,电源管理相片芯片
蓝雨夜 DIY/开源硬件专区
MSP430F5438学习笔记 FLAHS操作
1.前言MSP430F5438的片内FLASH可以当做EEPROM使用,该部分FLASH称为INFOFLASH,总共有4块每块128Byte。虽然INFOFLASH容量比较少,但是多数情况还是够用的。2.代码实现viewplaincopy//时钟默认情况//FLL时钟FLL选择XT1//辅助时钟ACLK选择XT132768Hz//主系统时钟MCLK选择DCOCLKDIV8000000Hz//子系统时钟SMCLK选
fish001 微控制器 MCU
CortexA8+DSP BeagleBoard 板子+扩展板
去年十一月份chipsee购买,基本没用过,九成新,运行Android完美,wifi链接完美。原价2700,出收价:2300,可淘宝链接:有诚意的加qq:307799870如有需要,可提供Linux下移植QT4.7+PowerVR的移植过程。------------------------------------------------------------------------------------------------------------
sblpp 淘e淘
有关NRF24L01与ARM板的连接 问题
现在准备用NRF24L01无线射频模块,手里还有一块smart210的板子,求大神告知如何将开发板与射频模块正确连接,谢谢,初学者希望您能指导一下,万分感谢有关NRF24L01与ARM板的连接问题2401用的是SPI吧?NRF24L01采用4线SPI通讯,你是要采用软件模拟SPI还是使用内部的SPI通讯模块呢?建议详细阅读一下SPI通讯部分,然后结合网上相关例程进行调试。spi接口,不过很多例子都是io模拟的.这些都是51的处理器,楼主用的啥处理器啊?smart210的板子应该
Agnoi RF/无线
msp-fet430UIF郁闷
我的笔记本只有4个usb口,以前只能用usb转rs232用编程器开发程序,现在看到了由usb接口的jtagfet十分激动,买了一个,可是软件又不支持v3.20真让我郁闷,现在有的回去用我的msp430prgs-III了。真是不胜感激!!msp-fet430UIF郁闷TI的msp-fet430UIF应该支持IAREW430V3.20A的。光盘里自带了3.21版本的编译器啊,直接安装好了,然后在到安装目录下去找到driver把USB在驱动下就没有问题了,完全可以使用,不过建议
gtongy 微控制器 MCU
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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