一.实验简介
通过定时器的timer模式来计时实现以1s为间隔将LED翻转。
二.板载定时器介绍
TM4C有两种定时器,一种为16/32bit的,一种是32/64bit的,两种定时器各有六个,对于每个定时器来说,它可以单独以较大的bit位作为一个定时器工作,也可以拆分为两个较小的bit位的定时器分别工作。比如对于16/32bit位的定时器,可以以32bit位的定时器工作,也可以以两个16bit的定时器A和B分别工作。
三.原理图及引脚分布
四.所需函数
用到的控制LED的GPIO相关函数与UART函数还有中断相关函数不再提起,有疑问的可以看我之前的文章
1.SysCtlPeripheralEnable(uint32_t ui32Peripheral)
参数:ui32Peripheral如果为16/32bit的定时器就是TIMER,如果是32/64bit的定时器就是WTIMER。
作用:使能外设
2.TimerConfigure(uint32_t ui32Base, uint32_t ui32Config)
参数:ui32Base为定时器基地址,ui32Config定时器所配置模式
作用:如果在定时器不拆分的情况下,可以将ui32Config设置为以下模式之一:
TIMER_CFG_ONE_SHOT – 单次减计数模式
TIMER_CFG_ONE_SHOT_UP – 单次加计数模式
TIMER_CFG_PERIODIC – 连续减计数模式
TIMER_CFG_PERIODIC_UP – 连续加计数模式
TIMER_CFG_RTC – 实时时钟模式
如果将定时器拆分的话则将ui32Config设置为TIMER_CFG_SPLIT_PAIR(分裂为一对)然后与以下模式进行或运算:
TIMER_CFG_A_ONE_SHOT – 定时器A单次减计数
TIMER_CFG_A_ONE_SHOT_UP –定时器A单次加计数
TIMER_CFG_A_PERIODIC – 定时器A连续减计数
TIMER_CFG_A_PERIODIC_UP – 定时器A连续加计数
TIMER_CFG_B_ONE_SHOT – 定时器B单次减计数
TIMER_CFG_B_ONE_SHOT_UP –定时器B单次加计数
TIMER_CFG_B_PERIODIC – 定时器B连续减计数
TIMER_CFG_B_PERIODIC_UP – 定时器B连续加计数
拆分之后的定时器AB都一样,用哪个就设置哪个,只是函数名有区别。
3.TimerLoadSet(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Value)
参数:ui32Base为定时器基地址,ui32Timer有TIMER_A,TIMER_B和TIMER_BOTH(单独A,单独B,AB都用)三种选择,在定时器拆分的情况下用哪个就设置哪个,在不拆分的情况下就设置为TIMER_A(对于其他函数也是,如果在级联的情况下还需要选择,那默认为选择TIMER_A),ui32Value为定时器加载值,一般来说定时时间=1/N,那么定时器加载值=SysCtlClockGet()/N-1,即根据自己的定时时间求出N,即可得定时器加载值。
此函数适用于16bit,32bit的定时器,即适用于16/32bit的定时器拆分与级联,32/64bit定时器的拆分三种情况,对于64bit的定时器,即32/64bit定时器的级联使用TimerLoadSet64。
作用:配置定时器加载值。
4.TimerIntRegister(uint32_t ui32Base, uint32_t ui32Timer,void (*pfnHandler)(void))
参数:ui32Base为定时器基地址,ui32Timer也是有TIMER_A,TIMER_B和TIMER_BOTH三种,对于级联的定时器设置为TIMER_A即可,void (*pfnHandler)(void)为中断函数名
作用:注册中断函数
5.TimerIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
参数:ui32Base为定时器基地址,ui32IntFlags为中断模式,在定时器状态下一般设置为TIMER_TIMB_TIMEOUT或TIMER_TIMA_TIMEOUT
作用:使能定时器中断
9.TimerEnable(uint32_t ui32Base, uint32_t ui32Timer)
参数:ui32Base为定时器基地址,ui32Timer也是有TIMER_A,TIMER_B和TIMER_BOTH三种。文章来源:https://www.toymoban.com/news/detail-605401.html
五.代码文章来源地址https://www.toymoban.com/news/detail-605401.html
timer_timer.c
/*此代码分别使用16/32bit的定时器拆分与32/64bit的定时器级联实现同样的功能*/
#include "timer.h"
#include "timer_timer.h"
#include "hw_memmap.h"
#include "gpio.h"
#include "sysctl.h"
#include "interrupt.h"
#include "hw_ints.h"
_Bool flag=0;
void TIMER_IRQHandler(void);
void TIMER_WID_IRQHandler(void);
//16/32bit定时器拆分
void Timer_Config(void)
{
//使能定时器TIMER0,16/32bit
SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0);
//配置定时器,将定时器拆分,并配置拆分后的定时器A为周期性计数
TimerConfigure( TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PERIODIC_UP);
//设置定时器A装载值,因为要1ms进一次中断,所以1ms=1/1000,
所以重装载值为SysCtlClockGet()/1000-1
TimerLoadSet( TIMER0_BASE, TIMER_A,
SysCtlClockGet()/1000-1);
//为定时器A注册中断函数
TimerIntRegister( TIMER0_BASE, TIMER_A,
TIMER_IRQHandler);
//使能time0的定时器A为超时中断
TimerIntEnable( TIMER0_BASE, TIMER_TIMA_TIMEOUT);
//设置中断优先级
IntPrioritySet( INT_TIMER0A, 0);
//使能中断
IntEnable( INT_TIMER0A);
IntMasterEnable();
//使能定时器
TimerEnable( TIMER0_BASE, TIMER_A);
}
void TIMER_IRQHandler(void)
{
static uint32_t time_count=0;
//读取定时器中断状态
uint32_t status=TimerIntStatus( TIMER0_BASE, true);
//清除中断标志位
TimerIntClear( TIMER0_BASE, status);
//1ms进一次中断
time_count++;
//进一千次,也就是1s,翻转flag
if(time_count==1000)
{
time_count=0;
flag=!flag;
}
}
//32/64bit的定时器级联
void Timer_Wid_Config(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
//设置不拆分并且周期计数
TimerConfigure(WTIMER0_BASE,TIMER_CFG_PERIODIC_UP);
TimerLoadSet64( WTIMER0_BASE, SysCtlClockGet()/1000-1);
//级联的情况下默认都是设置定时器A
TimerIntEnable( WTIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerIntRegister( WTIMER0_BASE, TIMER_A,
TIMER_WID_IRQHandler);
IntPrioritySet( INT_WTIMER0A, 1);
IntEnable( INT_WTIMER0A);
IntMasterEnable();
TimerEnable( WTIMER0_BASE, TIMER_A);
}
void TIMER_WID_IRQHandler(void)
{
static uint32_t time_count=0;
uint32_t status=TimerIntStatus( WTIMER0_BASE, true);
TimerIntClear( WTIMER0_BASE, status);
time_count++;
if(time_count==1000)
{
time_count=0;
flag=!flag;
}
}
timer_timer.h
#ifndef __TIMER_TIMER_H
#define __TIMER_TIMER_H
extern _Bool flag;
void Timer_Config(void);
void TIMER_IRQHandler(void);
void Timer_Wid_Config(void);
void TIMER_WID_IRQHandler(void);
#endif
led.c
#include "led.h"
#include "gpio.h"
#include "sysctl.h"
#include "hw_gpio.h"
#include "hw_memmap.h"
void LED_Config(void)
{
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF);
GPIODirModeSet( GPIO_PORTF_BASE, GPIO_PIN_2,
GPIO_DIR_MODE_OUT);
GPIOPadConfigSet( GPIO_PORTF_BASE, GPIO_PIN_2,
GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
}
led.h
#ifndef __LED_H
#define __LED_H
void LED_Config(void);
#endif
main.c
#include "tm4c123gh6pm.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_sysctl.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "uartstdio.h"
#include "usart.h"
#include "timer_timer.h"
#include "led.h"
void main(void)
{
SysCtlClockSet( SYSCTL_SYSDIV_4|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL);
LED_Config();
//Timer_Config();
Timer_Wid_Config();
while(1)
{
if(flag==0)
{
GPIOPinWrite( GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
}
else
{
GPIOPinWrite( GPIO_PORTF_BASE, GPIO_PIN_2, 0);
}
}
}
到了这里,关于TM4C123系列(五)————timer定时器(timer模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!