TM4C123系列(五)- Timer定时器模式详解

一.实验简介

通过定时器的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三种。

五.代码

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);
		}
	}
}
物联沃分享整理
物联沃-IOTWORD物联网 » TM4C123系列(五)- Timer定时器模式详解

发表评论