STM8S_002_TIM精确延时(阻塞式)

发布者:快乐的天使最新更新时间:2020-02-16 来源: eefocus关键字:STM8S  TIM  精确延时  阻塞式 手机看文章 扫描二维码
随时随地手机看文章

Ⅰ、写在前面

在某些特定场合,需要精确的延时(us级),特别是底层驱动。如果使用软件延时,延时会随系统时钟改变及各种因素影响而改变。因此,就需要使用TIM精确延时。


阻塞式延时:从延时开始至结束,程序一直阻塞在那里,不会跳转到其他地方(除中断)执行程序。不理解的朋友可以自己网上搜索答案。


TIM的种类和功能很多,本文是基础的知识,讲的比较简单,关于定时器更加强大和实用的功能可以关注我后面的文章。


为方便大家阅读,本文内容已经整理成PDF文件:


http://pan.baidu.com/s/1i5uWhJR


Ⅱ、TIM基础知识

STM8S的定时器(TIMER)类型有三类:基本定时器、通用定时器和高级定时器。基本定时器是8位计数的定时器,通用和高级定时器是16位计数的定时器。


定时器因类型不同,其功能和复杂程度不同,适用的场合也不同。本文以最基础、最简单的8位基础定时器来讲述TIM的延时。


强调一点:8位计数定时器,最大计数值为256。

TIM4基础定时器功能:


Ø 8位向上计数(UP-COUNTER)的自动重载计数器;


Ø 3位可编程的预分配器Prescaler(可在运行中修改),提供1, 2, 4, 8, 16, 32, 64 和128这8种分频比例。


Ø 中断产生:若使能了中断,在计数器更新时(计数器溢出)产生中断,本文未开启中断。


Ⅲ、软件工程源代码

1、关于工程

本文提供的工程代码是基于前面“STM8S_Demo”增加TIM定时器修改而来。初学的朋友可以参看我前面对应的基础文章,那些文章讲的比较详细。


软件工程源代码实现功能:通过阻塞式延时(500ms)改变LED亮灭状态来观察延时的大小。若要测量延时的精确性,可以将TIMDelay_Nms(500)改为其他TIMDelay_N10us(10)(延时100us),通过示波器测量LED引脚的频率为5KHz(周期为200us)。


2.软件概要说明

本文提供软件工程中包含的内容比较简单:


系统初始化:System_Initializes


v BSP_Initializes:时钟初始化CLK_Configuration和GPIO_Configuration初始化;


v TIMER_Initializes:定时器初始化,本文重点内容。


功能实现:while(1)


3.代码分析说明

关于BSP_Initializes中的内容这里不再详细说明,请见上一篇文章:STM8S_001_GPIO基础知识


本文重点讲述bsp_timer.c文件的内容:


A.TIMER_Initializes定时器初始化


void TIMER_Initializes(void)


{


  TIM4_TimeBaseInit(TIM4_PRESCALER_2, 79);


  TIM4_ClearFlag(TIM4_FLAG_UPDATE);


}


我们提供的软件工程是实现10us的延时,实现的公式为:16MHz / 2 / (79+1) = 0.1MHz(100KHz)。


第一个参数TIM4_PRESCALER_2:即2分频,这个参数具体为如下:


typedef enum


{


  TIM4_PRESCALER_1   = ((uint8_t)0x00),


  TIM4_PRESCALER_2   = ((uint8_t)0x01),


  TIM4_PRESCALER_4   = ((uint8_t)0x02),


  TIM4_PRESCALER_8   = ((uint8_t)0x03),


  TIM4_PRESCALER_16  = ((uint8_t)0x04),


  TIM4_PRESCALER_32    = ((uint8_t)0x05),


  TIM4_PRESCALER_64    = ((uint8_t)0x06),


  TIM4_PRESCALER_128   = ((uint8_t)0x07)


} TIM4_Prescaler_TypeDef;


第二个参数79:这个参数的值,实际上的自动重载寄存器(Auto-reload register)的值。从公式中可以看出,它是得出10us延时的来源。


很多人不理解为什么不是80,而是79呢?


原因是计数是从0开始的,0至79就是计数80个,因此这里是79。


语句TIM4_ClearFlag(TIM4_FLAG_UPDATE):


这条语句的意思很简单,清除UPDATE更新标志位。


B.延时N个10us:void TIMDelay_N10us(uint16_t Times)


void TIMDelay_N10us(uint16_t Times)


{


  TIM4_SetCounter(0);                             //计数值归零


  TIM4_Cmd(ENABLE);                            //启动定时器


  while(Times--)


  {


    while(RESET == TIM4_GetFlagStatus(TIM4_FLAG_UPDATE));


    TIM4_ClearFlag(TIM4_FLAG_UPDATE);


  }


  TIM4_Cmd(ENABLE);                             //关闭定时器


}


为什么是N个10us?


从上面定时器初始化可以知道,一个计数的过程(延时)是10us,参数Times代表要执行延时10us的次数。


TIM4_SetCounter(0);


每次启动定时器之前,将计数值归零,这样才能保证第一次计数(延时)准确。


while(RESET == TIM4_GetFlagStatus(TIM4_FLAG_UPDATE));


这一条语句代表程序在这里不停地读取更新标志位TIM4_FLAG_UPDATE(阻塞),直到读取标志位有效(计数满),则跳出这个while循环。


TIM4_ClearFlag(TIM4_FLAG_UPDATE);


清除更新标志位TIM4_FLAG_UPDATE。在上面标志位有效之后,需要清除,清除之后有进行下一个计数过程。


这里的启动和关闭定时器相信都能理解,从执行TIMDelay_N10us这一个函数开始到结束操作过程的开关。这里提醒一点:计数的过程的一个循环的过程,过程中尽量避免重复开关定时器(会有一定的耗时),我提供的TIMDelay_Nms其实严格来说不是很准确,该函数就是重复了开关。


C.具体实现功能


在main函数中的while里面就是本文源代码实现的具体功能,将一个LED灯(IO)高低交替输出,中间使用定时器比较精确的延时500ms,达到LED亮灭的效果。


代码:


while(1)


{


  LED_ON;                                      //LED亮


  TIMDelay_Nms(500);


  LED_OFF;                                     //LED灭


  TIMDelay_Nms(500);


}


这里TIMDelay_Nms函数严格来说存在一定的偏差,从上面的讲述,相信都知道如何修改来避免这样的误差。


Ⅳ、下载

STM8S资料:


http://pan.baidu.com/s/1o7Tb9Yq


软件源代码工程(STM8S-A02_TIM精确延时(阻塞式)):


http://pan.baidu.com/s/1c2EcRo0

关键字:STM8S  TIM  精确延时  阻塞式 引用地址:STM8S_002_TIM精确延时(阻塞式)

上一篇:IAR调试stm8单片机时延时函数被优化的问题
下一篇:STM8L101F3P6关于毫秒级延时函数不同写法的波形

推荐阅读最新更新时间:2024-11-08 14:57

stvd+stm8s: #error cpstm8 sx1276.c:70(35) missing prototype
stvd 4.3.9编译stm8s工程报如下错误: Compiling sx1276.c... cxstm8 +modsl +debug -pxp -no +split -pp -l -istm8s_stdperiph_driverinc -i C:Program Files (x86)COSMICCXSTM8Hstm8 -i C:Program Files (x86)STMicroelectronicsst_toolsetinclude -clDebug -coDebug sx1276.c #error cpstm8 sx1276.c:70(35) missing prototype #error cpstm8 sx1276.
[单片机]
STM8S GPIO模拟I2C的底层代码
底层代码 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 GPIO初始化设置 这颗STM8S上,具有真·开漏功能的引脚是PB4和PB5,这两个引脚也正是片上I2C外设的默认引脚。端口设置如下: PB4 :I2C的SCL时钟线,开漏输出模式 PB5 :I2C的SDA数据线,开漏输出模式 SCL和SDA初始化时,推荐选用高阻态输出 /** * @brief I2C端口初始化 * @param None * @retval None */ void I2C_GPIO_Init(void) {
[单片机]
stm8s串口奇偶校验学习笔记
以前用过stm32的串口,不过用的时候一般都是调用库函数,设置波特率,8位数据位,无校验,1位停止位。传输过程中也没有遇到过太多的问题,最近用stm8s,需要用到奇偶校验(至于什么是奇偶校验,网上资料很多),用了之后发现还是有些地方多需要注意的,下面把遇到的问题记录下来。 一、了解串口数据帧格式 二、了解stm8s的串口 查看stm8s参考手册: 可以看出,在STM8S中M位所定义是帧长度,而不是数据位的长度!也就是说M位所定位的长度为“数据位+奇偶校验位”个数的总和。当数据位为8位时,不使用奇偶校验的时候,M的长度为8位;而要使用奇偶校验的时候,M的长度应该为9位!所以编写程序的时候不能简单的只改变校验位的设置; 三、程
[单片机]
<font color='red'>stm8s</font>串口奇偶校验学习笔记
STM8S---电源功耗管理之停机模式(halt)实现
主要内容简介 影响功耗的主要因素 电源系统 时钟管理 运行模式和低功耗模式 运行模式 等待模式 活跃停机模式 停机模式 功耗与唤醒事件的测量与结果 功耗管理要点 要点摘要   停机模式(Halt):此模式下单片机的功耗最低,振荡器,CPU和外设的时钟都被关闭,主电压调压器断电。可用复位或外部中断唤醒,唤醒后之前运行的寄存器数据等都保持不变,且从HALT处继续执行程序。 停机模式下的功耗测量结果(MVR关LPVR开):12 运行模式下的功耗测量结果(从RAM运行,不是从Flash开始):12 停机模式下的唤醒时间测量结果:12 测试程序 /* Function: 电源管理:停机(Ha
[单片机]
利用Keil u3调试,精确实现软件延时
用定时器延时,有时候显得有点麻烦,我们不如考虑软件精确延时,软件延时无非就是利用for或while多重循环。以前用到延时函数时,都是从网上下载别人写好的延时子程序。延时5ms,400ms,1s, ,这些延时函数的函数名中都清清楚楚地标明了延时的时间,可我一直不知道这些函数是如何编写的,确切地说,是如果根据延时时间来确定循环次数的。如果是纳秒级的延时,可以通过示波器来观察波形,或者反汇编一下,计算一下指令执行时间,但如果延时时间相对较长,示波器便无能为力了。这几天好好看了一下Keil调试,发现Keil的功能实在是太强大了。利用Keil uVersion的调试就可以写出精确的软件延时程序。以下是我的简单小结,文中所有程序都是在Xtal=
[单片机]
关于STM32的 一个TIM1 的PWM程序和PWM简单使用
高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。共有4个通道有 死区有互补。 先是配置IO脚: GPIO_InitTypeDef GPIO_InitStructure; /* PA8设置为功能脚(PWM) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*P
[单片机]
关于STM32的 一个<font color='red'>TIM</font>1 的PWM程序和PWM简单使用
STM8S:Debug调试正常,烧录程序运行不正常
最近有一个项目需要用到STM8S103F3单片机。在开始之前以为会很容易,可是实际操作起来,却遇到不少问题 。其中最令我感到困惑的一个问题是:我在调试程序的时候程序可以运行正常,但当我把程序烧录进去断电重启后却运行不正常。 试了很多方法,都没有找到问题所在。最后,我把Start-up file 选择默认的就可以。之前不知道在哪里看到过可以不使用系统的默认启动文件,可以直接在stm8_interrupt_vector.c中将_stext()改为main();现在看来真的是害死个让人。 关于STM8S的启动过程: 1)首先bootloader(ROM中)从0x6000地址启动。 2)从bootloader跳转到0x8000(内部F
[单片机]
【STM32电机方波】记录3——TIM1时基初始化配置
定时器分类 : STM32F1x 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。 基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。 通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。 高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。 高级定时器TIM1的库函数: 定时器TIM1时基结构体缺省值: { TI
[单片机]
【STM32电机方波】记录3——<font color='red'>TIM</font>1时基初始化配置
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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