TM4C123库函数学习(2)--- LED闪烁,滴答定时器精准延时

简介: TM4C123库函数学习(2)--- LED闪烁,滴答定时器精准延时

前言

(1)阅读本文之前,需要先看TM4C123库函数学习(1)— 点亮LED+TM4C123的ROM函数简介+keil开发环境搭建篇。

(2)TM4C123是M4的内核,拥有一个24位向下计数的SysTick定时器。,可用于生成定期中断。

<1>它可以作为系统的系统时钟节拍,可以用来轮询或者用于任务调度。

<2>滴答定时器可作为RTOS的时基单元。

<3>一种使用系统时钟的高速报警定时器。

<4>可变速率报警或信号定时器-持续时间是范围-依赖于使用的参考时钟和计数器的动态范围。

<5>基于缺席/会议时间的内部时钟源控制。STCTRL控制和状态寄存器中的COUNT位可以用来确定一个动作是否在设定的时间内完成,作为动态时钟管理控制循环的一部分。

(3)我们如果是裸机开发,这个定时器一般用于精准延时,或者定时器调度。


函数介绍

ROM_SysCtlClockGet()

这个函数可以获取系统时钟的速率。按照上文,我们将系统时钟设置为80MHZ,所以这个函数最终会返回80 000 000。

/****** 函数声明 ******/
//这个存放在ROM
uint32_t ROM_SysCtlClockGet(void);
//这个是存放在flash
uint32_t SysCtlClockGet(void);
/****** 函数介绍 ******/
/* 作用 : 获取系统时钟频率
 * 传入参数 : 无
 * 返回参数 : 一个32bit的数据,为系统时钟速率。
*/


ROM_SysTickPeriodSet()

(1)设置SysTick计数器的周期。如果我们写成SysTickPeriodSet(SysCtlClockGet() / 1000000UL);表示每过1us进入一次滴答定时器中断函数。

(2)可能会有人不理解,为什么会这样呢?

<1>首先,我上面说了SysCtlClockGet()可以获取系统时钟频率,因为现在是80MHZ,所以返回80MHZ,然后除以1MHZ,所以SysTickPeriodSet(SysCtlClockGet() / 1000000UL); == SysTickPeriodSet(80);

<2>因为系统时钟为80MHZ,所以时钟每跳变一次是1/80us,而我们设置的滴答计数器的周期为80,所以每过1us进入一次滴答定时器中断。


/****** 函数声明 ******/
//这个存放在ROM
void ROM_SysTickPeriodSet(uint32_t ui32Period);
//这个是存放在flash
void SysTickPeriodSet(uint32_t ui32Period);
/****** 函数介绍 ******/
/* 作用 : 设置SysTick计数器的周期。
 * 传入参数 :
     * ui32Period : 一个32bit的数据,为滴答定时器周期。
 * 返回参数 : 无
*/

SysTickIntRegister()

(1)这个用于注册滴答定时器中断函数,当滴答定时器溢出时候,进入传入的那个函数。

(2)这个有没有ROM函数,不清楚,反正我没有找到。

/****** 函数声明 ******/
//这个是存放在flash
void SysTickIntRegister(void (*pfnHandler)(void));
/****** 函数介绍 ******/
/* 作用 : 注册滴答定时器中断函数
 * 传入参数 : 
     * void (*pfnHandler)(void):滴答定时器溢出中断的中断函数,注意,这个中断服务函数无传入参数,无返回值!!!
 * 返回参数 : 无
*/

ROM_SysTickIntEnable()

使能SysTick中断,如果不调用这个函数,滴答定时器的溢出中断将无法被调用。

/****** 函数声明 ******/
//这个存放在ROM
void ROM_SysTickIntEnable(void);
//这个是存放在flash
void SysTickIntEnable(void);
/****** 函数介绍 ******/
/* 作用 : 使能SysTick中断
 * 传入参数 : 无
 * 返回参数 : 无
*/


ROM_SysTickIntEnable()

使能SysTick计数器。如果没有使能滴答定时器,那么滴答定时器将不会计数,同时中断服务函数永远也进不去。

/****** 函数声明 ******/
//这个存放在ROM
void ROM_SysTickIntEnable(void);
//这个是存放在flash
void SysTickIntEnable(void);
/****** 函数介绍 ******/
/* 作用 : 使能SysTick计数器
 * 传入参数 : 无
 * 返回参数 : 无
*/


实操

main.c

#include "stdio.h"
#include <stdint.h>
#include <stdbool.h>
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_gpio.h"
#include "debug.h"
#include "fpu.h"
#include "gpio.h"
#include "pin_map.h"
#include "rom.h"
#include "sysctl.h"
#include "uart.h"
#include "uartstdio.h"
#include "SystickTime.h"
int main(void)
{  
  ROM_FPUEnable();//使能浮点单元。这个函数必须在执行任何硬件浮点运算之前被调用;如果不这样做,将导致NOCP使用错误。
  ROM_FPULazyStackingEnable();//浮点延迟堆栈,减少中断响应延迟  
  ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |SYSCTL_OSC_MAIN);//配置系统时钟,系统时钟频率400M/2/2.5=80M
  ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);        //使能GPIOF外设 
  ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4); //将LED设置为输出
  initTime();        //初始化滴答定时器
  while(1)
  {
    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, !GPIO_PIN_4);          //置低位点亮
    delay_ms(100);  
    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4); //置高位熄灭
    delay_ms(100);
  }
}


SystickTime.c

#include <stdint.h>
#include <stdbool.h>
#include "Time.h"
#include "SystickTime.h"
#include "sysctl.h"
#include "systick.h"
static volatile uint32_t counter;
/* 滴答定时器中断,每微妙进入一次,count表示过了多少微妙,最多计时71分钟*/
static void SycTickHandler(void) {
  counter++;
}
/* 作用 : 初始化滴答定时器,让滴答定时器每微妙进入一次中断
 * 传入参数 : 无
 * 返回值 : 无
*/
void initTime(void) {
  SysTickPeriodSet(SysCtlClockGet() / 1000000UL); // 1000表示毫秒,1000000表示微秒
  SysTickIntRegister(SycTickHandler);  //注册滴答定时器中断服务函数
  SysTickIntEnable();  //使能SysTick中断
  SysTickEnable();     //使能SysTick计数器
}
/* 作用 : 进行毫秒延时
 * 传入参数 :
     ms : 要延时多少毫秒
 * 返回值 : 无
*/
void delay(uint32_t ms) {
  delayMicroseconds(ms * 1000UL);
}
/* 作用 : 进行微妙延时
 * 传入参数 : 
     us : 要延时的微妙数
 * 返回值 : 无
*/
void delayMicroseconds(uint32_t us) {
  uint32_t start = micros(); //记录准备开始延时的时间,单位微秒
  //如果当前时间减去开始延时的时间小于传入值,阻塞。
  while ((int32_t)(micros() - start) < us) {
    // Do nothing
  };
}
/* 作用 : 开机到现在返回过了多少毫秒
 * 传入参数 : 无
 * 返回值 : 返回开机到现在过了多少毫秒
*/
uint32_t millis(void) {
  return counter / 1000UL;
}
/* 作用 : 开机到现在返回过了多少微秒
 * 传入参数 : 无
 * 返回值 : 返回开机到现在过了多少微秒
*/
uint32_t micros(void) {
  return counter;
}
/* 作用 : 延时时间,单位毫秒
 * 传入参数 : 要延时的毫秒数
 * 返回值 : 无
*/
void Delay_Ms(uint32_t x)
{
  delay(x);
}
/* 作用 : 延时时间,单位毫秒
 * 传入参数 : 要延时的微妙数
 * 返回值 : 无
*/
void delay_ms(uint32_t x)
{
  Delay_Ms(x);
}
/* 作用 : 延时时间,单位微秒
 * 传入参数 : 要延时的微秒数
 * 返回值 : 无
*/
void delay_us(uint32_t x)
{
  delayMicroseconds(x);
}
/* 作用 : 延时时间,单位微秒
 * 传入参数 : 要延时的微秒数
 * 返回值 : 无
*/
void Delay_Us(uint32_t x) 
{
  delayMicroseconds(x);
}


SystickTime.h

#ifndef __SYSTICKTIME_h__
#define __SYSTICKTIME_h__
void initTime(void);                 //初始化滴答定时器
void delay(uint32_t ms);             //进行毫秒延时
void delayMicroseconds(uint32_t us); //进行微妙延时
uint32_t millis(void);               //返回开机到现在过了多少毫秒
uint32_t micros(void);               //返回开机到现在过了多少微秒
void Delay_Ms(uint32_t x);           //延时时间,单位毫秒
void Delay_Us(uint32_t x);           //延时时间,单位微秒
void delay_ms(uint32_t x);           //延时时间,单位毫秒
void delay_us(uint32_t x);           //延时时间,单位微秒
#endif
目录
相关文章
|
Linux 调度
按键消抖的两种方法--中断延迟工作与定时器
按键消抖的两种方法--中断延迟工作与定时器
686 0
|
4月前
51开发板同一程序实现数码管实现时钟显示、秒表计时。通过独立按键选择模式(时钟/秒表)、时间的重定义
51开发板同一程序实现数码管实现时钟显示、秒表计时。通过独立按键选择模式(时钟/秒表)、时间的重定义
138 3
|
4月前
|
C语言
【51单片机】LCD1602显示字符串,时间、时间+按键校准、秒表计时的功能代码。
【51单片机】LCD1602显示字符串,时间、时间+按键校准、秒表计时的功能代码。
|
4月前
【51单片机】通过定时器中断 在8位数码管显示时间
【51单片机】通过定时器中断 在8位数码管显示时间
定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”
定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”
STM32学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
原理:当捕捉到信号的跳变沿时,将CNT的值所存到捕获寄存器CCR中,然后把两次的值相减,就可以得到脉宽或者频率。
1544 0
【单片机期中测试】4.按键不同时长控制流水灯
【单片机期中测试】4.按键不同时长控制流水灯
63 0
|
存储 调度
51单片机--定时器与按键控制流水灯模式
51单片机--定时器与按键控制流水灯模式
483 0
蓝桥杯使用定时器代替延时控制按键
蓝桥杯使用定时器代替延时控制按键
78 0