ZYNQ之定时器

一、定时器简介

定时器作为 PS 的重要组成部分,可以不受 CPU 的干预,自己独立运行,来完成计时、定时、中断以及计算来自 MIO 或 EMIO 引脚的信号脉冲宽度。

在 ZYNQ 嵌入式系统中,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器( GT)。PS 中还有一个 24 位的系统看门狗定时器( SWDT)和两个 TTC( Triple Timer Counters)

系统看门狗定时器可以在系统发生灾难性的故障时(如 PS 中的 PLL 工作异常)发出信号, 使得系统程序重新启动,保证了系统安全可靠的运行。SWDT可以工作在CPU频率的1/4或1/6(CPU_1x),也可以工作在设备外部或PL提供的时钟下,并向它们输出一个复位信号。

TTC 用于计算来自 MIO 引脚或 EMIO 引脚的信号脉冲宽度,每个 TTC 都有三个独立的计数器。TTC只能工作在CPU频率的1/4或1/6(CPU_1x)

定时器的系统框如下图

ZYNQ之定时器_第1张图片

 图中的定时器连接到中断控制器( Interrupt Controller),可以很方便的使用定时器来完成定时器中断的实验。其中私有定时器( CPU Private Timer)是最为常用的。

私有定时器的时钟频率为 CPU 时钟频率的一半。如 ARM 的工作时钟频率为 666.666Mhz,则私有定时器的时钟频率为 333.333Mhz。

私有定时器的特性

①32 位计数器,当计数器递减至 0 后产生中断
②8 位预分频计数器,可以更好的控制中断周期

③可以配置单次定时或者自动重载模式
④通过配置起始计数值来设置定时时间

 二、定时器编程

由于 ARM 处理器自带了私有定时器,所以在定时器方面搭建嵌入式系统时,不需要额外添加定时器,除非使用其他定时器

定时器初始化

    int Status;
	//私有定时器初始化
	XScuTimer_Config *timer_cfg_ptr;
	timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
	if (timer_cfg_ptr == NULL)
	{
		return XST_FAILURE;
	}
	Status = XScuTimer_CfgInitialize(&Timer, timer_cfg_ptr,timer_cfg_ptr->BaseAddr);
	if (Status != XST_SUCCESS)  //判断是否初始化成功
	{
		return XST_FAILURE;
	}

	XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE); // 加载计数周期
	XScuTimer_EnableAutoReload(&Timer); // 设置自动装载模式

主要是初始化私有定时器和设置自动重装值(定时器溢出时间)以及模式 。

定时时间计算:

私有定时器的时钟频率为CPU频率的一半,这里ZYNQ默认工作频率650Mhz,则私有定时器的时钟频率为325Mhz,若定时时间为 T,则写入重装值为 :T /  (1 /325Mhz ) 。 

一般使用定时器基本上都有使用中断,所以还需要初始化定时器相关中断

    //初始化中断控制器
	XScuGic_Config *gic_cfg; //中断控制器配置信息
	gic_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (gic_cfg == NULL)
	{
		return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(&Intc,gic_cfg,gic_cfg->CpuBaseAddress);
	if (Status != XST_SUCCESS)  //判断是否初始化成功
	{
		return XST_FAILURE;
	}
	//初始化异常处理
	Xil_ExceptionInit();
	//CPU中断异常注册
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&Intc);
	//使能处理器中断
	Xil_ExceptionEnable();;

	//设置定时器中断:  timer_intr_handler 中断处理函数
	XScuGic_Connect(&Intc, TIMER_IRPT_INTR,(Xil_ExceptionHandler)timer_intr_handler, &Timer);


	XScuGic_Enable(&Intc,TIMER_IRPT_INTR);//使能 GIC 中的定时器中断
	XScuTimer_EnableInterrupt(&Timer); //使能定时器中断

注意:定时器初始化一定要放在中断初始化的前面。

中断的初始化基本上都是固定的套路。这里设置中断函数为timer_intr_handler()

void timer_intr_handler(void *CallBackRef)
{
	XScuTimer *timer_ptr = (XScuTimer *) CallBackRef;
    ....
	//清除定时器中断标志
	XScuTimer_ClearInterruptStatus(timer_ptr);
}

 


 

你可能感兴趣的:(ZYNQ,单片机,嵌入式硬件)