在我们日常使用单片机的时候,延时一般采用循环的方式,但是这样的方式只能用于粗略的延时,但我们需要精准的时间控制的时候,便需要利用定时器获得精确的延时。

本次采用TM4内的滴答定时器

文章目录

  • 1、滴答定时器使用
    • (1)初始化代码
    • (2)解释
  • 2、利用定时器进行延时的方法
    • 1、精髓:micros()函数
    • 2、利用micros()实现延时
  • 测试例程1
  • 测试例程2

1、滴答定时器使用

滴答定时器结构比较简单,在TM4内部是一个24位自减的计数器。

(1)初始化代码

SysTickPeriodSet(SysCtlClockGet()/1000);    // 1ms
SysTickIntRegister(SysTick_IntHandler);
SysTickIntEnable();
SysTickEnable();

(2)解释

1、首先进行周期设置,用系统频率除以1000,表示1ms的中断。

计算方法:定时器的工作原理便是在系统时钟驱动下进行计数,假设系统时钟频率是10KHz,代表1秒钟可以计10000个数,即:即计一个数的时间t = 1/10000 s = 0.1 ms,那么如果我要设置一个一毫秒的中断,即需要数10个数,因为10*(1/10000) = 1/1000 s = 1ms

因此对于SysTickPeriodSet()这个函数来说,我需要一毫秒的中断,便将系统时钟除以1000作为参数传进去即可。

2、然后设置中断函数的地址

SysTick_IntHandler便是中断处理函数的函数名称,代表该函数的地址。

3、使能中断,打开定时器

SysTickIntEnable();
SysTickEnable();

4、写中断处理函数

这里是设置了一个全局变量,每进入一次中断便将其加1。

void SysTick_IntHandler(void)
{System_Time_ms++;
}

5、测试:见文末测试例程1。

2、利用定时器进行延时的方法

1、精髓:micros()函数

首先我们需要知道系统的当前精确时间,这里实现了一个micros()函数,以微秒为单位。

uint32_t micros(void)
{register uint32_t ms, tick;     do{ms   = System_Time_ms;tick = HWREG(NVIC_ST_CURRENT); }while(ms != System_Time_ms);return (ms+1)*1000 - tick/usTicks;
}

在这个函数中,因为滴答定时器的中断是1ms,所以System_Time_ms便是系统运行的ms数,HWREG(NVIC_ST_CURRENT)是针对寄存器的操作,获得当前滴答定时器内部的计数值。usTicks = Clock/1000000,所以tick/usTicks = tick*(1000000/Clock),即将定时器计数值转换为实际的us数,然后通过(ms+1)*1000 - tick/usTicks的运算,即得到了us级的系统时间。

2、利用micros()实现延时

这里的逻辑就是进入函数时记录当前时间,然后一直用实时时间和开始时间进行比较,作差,得到延时时间。

void delay_us(uint32_t nus)
{uint32_t t0 = micros();while(micros() - t0 < nus);
}void delay_ms(uint32_t nms)
{uint32_t t0 = micros();while(micros() - t0 < nms*1000);
}

测试:见测试例程2。

测试例程1

功能:打印系统当前时间,以毫秒为单位。

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/systick.h"
#include <stdio.h>uint32_t System_Time_ms = 0;void delay_ms(int n)
{for(int i = 0; i < n; i++)SysCtlDelay(SysCtlClockGet()/3000);
}//重写fputc函数以支持printf
int fputc(int ch, FILE *f)
{UARTCharPut(UART0_BASE,(unsigned char)ch);//如果用其他串口,只需修改基址(UART0_BASE)即可。return ch;
}void SysTick_IntHandler(void)
{System_Time_ms++;
}int main()
{   SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |  SYSCTL_XTAL_16MHZ);//初始化串口0SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));GPIOPinConfigure(GPIO_PA0_U0RX);GPIOPinConfigure(GPIO_PA1_U0TX);GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);UARTConfigSetExpClk(UART0_BASE, 16000000, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));//初始化滴答定时器SysTickPeriodSet(SysCtlClockGet()/1000);    // 1msSysTickIntRegister(SysTick_IntHandler);SysTickIntEnable();SysTickEnable();while(1){printf("%d\n", System_Time_ms);//打印系统时间delay_ms(100);}
}

测试例程2

功能:延时10ms,然后打印出来花费的具体时间。

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/systick.h"
#include "inc/hw_types.h"
#include "inc/hw_nvic.h"
#include <stdio.h>volatile uint32_t usTicks        = 0;
volatile uint32_t System_Time_ms = 0;void     delay_us(uint32_t nus);
void     delay_ms(uint32_t nms);
int      fputc(int ch, FILE *f);
void     SysTick_IntHandler(void);
uint32_t micros(void);
void     UART0_Init(uint32_t Baud);
void     SysTick_Init(void);int main(void)
{   SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |  SYSCTL_XTAL_16MHZ);UART0_Init(115200);SysTick_Init();uint32_t t0,t1;while(1){t0 = micros();delay_ms(10);t1 = micros();printf("%d\n", t1-t0);//打印系统时间}
}void delay_us(uint32_t nus)
{uint32_t t0 = micros();while(micros() - t0 < nus);
}void delay_ms(uint32_t nms)
{uint32_t t0 = micros();while(micros() - t0 < nms*1000);
}int fputc(int ch, FILE *f)
{UARTCharPut(UART0_BASE,(unsigned char)ch);return ch;
}void SysTick_IntHandler(void)
{System_Time_ms++;
}uint32_t micros(void)
{register uint32_t ms, tick;     do{ms   = System_Time_ms;tick = HWREG(NVIC_ST_CURRENT); }while(ms != System_Time_ms);return (ms+1)*1000 - tick/usTicks;
}void UART0_Init(uint32_t Baud)
{SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));GPIOPinConfigure(GPIO_PA0_U0RX);GPIOPinConfigure(GPIO_PA1_U0TX);GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);UARTConfigSetExpClk(UART0_BASE, 16000000, Baud, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}void SysTick_Init(void)
{SysTickPeriodSet(SysCtlClockGet()/1000);    // 1msSysTickIntRegister(SysTick_IntHandler);SysTickIntEnable();SysTickEnable();usTicks = SysCtlClockGet() / 1000000;       // usTicks = 80
}

8、TM4单片机的滴答定时器,及利用定时器精确延时相关推荐

  1. 基于STM32滴答时钟的多任务定时器

    基于STM32滴答时钟的多任务定时器 基于STM32滴答时钟的多任务定时器 概述 声明:此定时器仅提升个人编程能力和学习使用,不得用于商用,用于商用一切后果自行负责. API说明 滴答时钟初始化并创建 ...

  2. c语言流水灯定时器延时,实现流水灯以间隔500ms的时间闪烁(系统定时器SysTick实现的精确延时)...

    /** ****************************************************************************** * @file main.c * ...

  3. 实现流水灯以间隔500ms的时间闪烁(系统定时器SysTick实现的精确延时)

    /** ****************************************************************************** * @file main.c * ...

  4. STM32系统滴答_及不可不知的延时技巧

    我想每个单片机爱好者及工程开发设计人员都有过点灯的经历.流水灯是个好东西,尤其是在调试资源有限的环境中,有时会帮上大忙. 然在最初入门时,如何让这些小灯们按照我们的想法欢快地跑起来呢,绝大多数小朋友的 ...

  5. STM32系统滴答_及不可不知的延时技巧 - (上)

    文章转载自https://my.oschina.net/czzhu/blog/228596:作者:小汉憨憨 摘要: 尤应强调注意的是SysTick 中断优先级. 我想每个单片机爱好者及工程开发设计人员 ...

  6. 51单片机实例学习二 按键中断识别、定时器、利用定时器产生乐曲、数摸转换 ADC0804和DAC0832

    六.按键中断识别 [实验任务] 采用中断技术,每按一下按键,计数器加1,并用LED显示出来. [硬件电路] 注意:我们只用4位数码管中的两位. 注意:a接P0.0;b接P0.1;c接P0.3-- 注意 ...

  7. STM32系统滴答_及不可不知的延时技巧 - (下)

    本文转载自https://my.oschina.net/czzhu/blog/261802:作者:小汉憨憨 摘要: 单片机非阻塞延时巧妙的软件设计. 下面为大家介绍一个曾见过的在裸机系统中,非阻塞延时 ...

  8. 嵌入式开发(7)系统定时器(SysTick)之延时函数运用

    目录 一.系统定时器 1. 简介 2.工作原理 3.频率的概念 二.库函数SysTick定时器操作 系统定时器配置 三.寄存器SysTick定时器操作 1.系统定时器的用途 2.寄存器 3.官方示例 ...

  9. 【STM32】HAL库-系统滴答定时器SysTick

    SysTick定时器被捆绑在NVIC中,是一个简单的定时器,对于CM3.CM4内核芯片,都有Systick定时器.Systick定时器常用来做延时,或者实时系统的心跳时钟.这样可以节省MCU资源,不用 ...

最新文章

  1. Team Foundation Server Beta3 安装指南
  2. 一 Struts2 开发流程
  3. Java平滑处理什么意思_为何要进行数据平滑处理?
  4. python 发包爬取中国移动充值页面---可判断手机号是否异常
  5. 线性回归(一)---一元线性回归
  6. linux非root用户关机,在Linux中普通用户图形界面登录以后为什么可以关机或者重启机器...
  7. 在MVC3中使用code first生成数据局库并操作数据库
  8. 英特尔加入 GPU 战局,终用上 6nm 工艺?
  9. java截取字符串函数
  10. mysql使用GROUP BY分组实现取前N条记录的方法或最近几条消费记录
  11. 两部门:解除蒙古国部分地区口蹄疫疫情禁令
  12. axure8.0注册码
  13. 第二章 一元函数的导数与微分概念及其计算
  14. 京东E卡购买api接口
  15. 华为畅享20 pro 和华为畅享Z 的区别 哪个好
  16. Echarts折线图X轴Y轴图例位置调整
  17. Java——博主的学习路线
  18. 记一次 Centos7.x Hadoop3.x集群安装部署 Pig 0.17.0
  19. 2022年废纸价格预测
  20. 初玩SM2259XT2+B27A自制固态开卡成功,SM2259XT2量产工具和SM2258XT类似

热门文章

  1. 对抗生成神经网络-GAN通俗理解
  2. Oracle中根据中文获取拼音首字母
  3. Ajax之【Ajax异步实现步骤】
  4. EntityFramework之领域驱动设计实践(五)
  5. Ant工具 ant的安装与配置 ant作用
  6. 两位数求和(xhh)
  7. R语言 NetCoMi包 Co-occurrence网络图 微生物16S 网络比较 核心物种
  8. javascript常用方法 – String
  9. 2022年初级审计师考试冲刺试题及答案
  10. 云计算基础知识培训讲义