ZYNQ(二):PS定时器使用

说明: 开发软件 :vivadeo 和SDK
开发平台: 黑金的zynq7010

一、具有中断的定时器
二、简单定时器

说明:
私有定时器
zynq中每个ARM core都有自己的私有定时器,私有定时器的工作频率为CPU的一半,比如Miz702或者zedboard的ARM工作频率为666MHZ,则私有定时器的频率为333MHz.
私有定时器的特性如下:
(1)32为计数器,达到零时产生一个中断
(2)8位预分频计数器,可以更好的控制中断周期
(3)可配置一次性或者自动重加载模式
(4)定时器时间可以通过下式计算:
定时时间 = [(预分频器的值 + 1) (加载值 + 1)]/定时器频率

一、具有中断的定时器
定时器的配置文件:xscutimer.c xscutimer.h
CPU的配置文件 :xparameter.h
说明:有关PS控制ARM内部的定时器中断。具体步骤:

①、定位配置定时器设备ID

ConfigPtr = XScuTimer_LookupConfig(TimerDeviceId); 

②、定时器配置初始化

XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,
					ConfigPtr->BaseAddr) ;

③、定时器进行自检查看主结构配置是否正常

 XScuTimer_SelfTest(TimerInstancePtr) ;

④、根据定时器的中断ID 获取中断的配置

TimerSetupIntrSystem(XScuGic *IntcInstancePtr,
			      XScuTimer *TimerInstancePtr, u16 TimerIntrId)

二、一般开启定时器中断流程:

0、根据中断ID 获取中断配置


```c
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);   

 
1、初始化中断配置和主结构体是否正确

```c
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,   

2、初始化异常处理功能(这个函数支持的处理器ARM Cortex-A53 Cortex-R5,)、

Xil_ExceptionInit();  //异常初始化

3、异常处理注册

Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,      
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				IntcInstancePtr);
    

4、配置中断处理和配置中断服务函数(需要自行编一个中断服务函数)

Status = XScuGic_Connect(IntcInstancePtr, TimerIntrId,
				(Xil_ExceptionHandler)TimerIntrHandler, //中断服务函数
				(void *)TimerInstancePtr);
    

5、中断服务函数里面要判断标志位

void TimerIntrHandler(void *CallBackRef) {
XScuTimer_IsExpired(TimerInstancePtr) //标志位触发
XScuTimer_ClearInterruptStatus(TimerInstancePtr); //清除标志位
XScuTimer_DisableAutoReload(TimerInstancePtr)//关闭自动重装载值 关闭中断
}		

6、使用定时器终端编号使能中断开关

XScuGic_Enable(IntcInstancePtr, TimerIntrId); //使能

7、使能定时器中断

XScuTimer_EnableInterrupt(TimerInstancePtr);  //使能中断

8、异常处理使能

Xil_ExceptionEnable();  //异常处理使能
#endif

⑥、设置自动装载模式

XScuTimer_EnableAutoReload(TimerInstancePtr); //设能自动 冲重装载模式

⑦、配置自动重装载值

XScuTimer_LoadTimer(TimerInstancePtr, TIMER_LOAD_VALUE); //加载计时间   注册计数器

⑧、启动定时器

XScuTimer_Start(TimerInstancePtr);   //启动定时器

至此就可以使用到定时器了,另外还有处理两个函数,禁能和关闭定期函数:
TimerDisableIntrSystem(IntcInstancePtr, TimerIntrId); //禁能定时器
XScuTimer_DisableAutoReload(TimerInstancePtr); //禁止自动载入模式

ZYNQ(二):PS定时器使用_第1张图片

二、简单定时器(非中断模式)
ZYNQ里面的定时器API函数功能:

①、获取配置信息

根据ID查找配置信息
XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId)

②初始化定时器

根据ID配置信息填充InstancePtr结构。InstancePtr结构包含定时器信息
s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, XScuTimer_Config *ConfigPtr, 
                            u32 EffectiveAddress)

③设置定时器初始值

通过InstancePtr结构定位到对应的设备,装载定时值Value
XScuTimer_LoadTimer(InstancePtr, Value)	

④启动和停止定时器

通过InstancePtr结构定位到对应的设备、然后启动
void XScuTimer_Start(XScuTimer *InstancePtr)

通过InstancePtr结构定位到对应的设备、然后将其停止
void XScuTimer_Stop(XScuTimer *InstancePtr);

⑤、获取当前计数值

通过InstancePtr结构定位到对应的设备、获取定时器当前时间,当返回值为0时,定时时间到
u32   XScuTimer_GetCounterValue(InstancePtr)	

⑥、重新启动计数器

通过InstancePtr结构定位到对应的设备、然后重新启动计数。
 u32    XScuTimer_RestartTimer(InstancePtr)

历程代码:

XScuTimer XSc_Timer;
#define  TIMER_DEVICE_ID    XPAR_XSCUTIMER_0_DEVICE_ID
#define  TIMER_LOAD_VALUE  (XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ/2 -1)
int  timerSet_S(void)
{
//---------------------------------------
	int status = 0;
	int count = 0;
	int keep_timer = 0//---------------------------------------
	XScuTimer_Config *ConfigPtr;
	XScuTimer *TimerInstancePtr = &XSc_Timer;

	ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
	XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,ConfigPtr->BaseAddr);
	XScuTimer_LoadTimer(TimerInstancePtr, TIMER_LOAD_VALUE);
	XScuTimer_Start(TimerInstancePtr);
	while(1) {
		keep_timer = XScuTimer_GetCounterValue(TimerInstancePtr);
		if(keep_timer == 0){  //定时到
			XScuTimer_RestartTimer(TimerInstancePtr);//装载初始值重新开始计数
			xil_printf("计数器  计时完成了  计算的次数是   = %d   \n'r", count++);
			if(count==2) {
                        return status;
			}
		}
		else{
               //打印出当前计数值
               xil_printf("Timer is still running (Timer value = %d)\n\r", keep_timer );
		}
	}
	return status;
}

代码流程框图:
ZYNQ(二):PS定时器使用_第2张图片

延时器代码实现

XScuTimer Timer;
XScuTimer *TimerInstancePtr;
#define  TIMER_DEVICE_ID    XPAR_XSCUTIMER_0_DEVICE_ID
#define  TIMER_LOAD_VALUE   (XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ/2 -1)
static int  SystemTimetInit(int num);
static void delayed(int count,int Timer);
#define delayed_s(count)   delayed(count,1*1)
#define delayed_ms(count)  delayed(count,1*1000)
#define delayed_us(count)  delayed(count,1*1000*1000)

static int  SystemTimetInit(int num)
{
	char * FUNCTION = "[SystemTimetInit]";
//---------------------------------------
	int status = 0;
	XScuTimer_Config *ConfigPtr;
    TimerInstancePtr = &Timer;

//-----------------XScuTimer_LookupConfig-----------------------//
	ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
	if(ConfigPtr == NULL) {
		xil_printf("%s :XScuTimer_LookupConfig error exit Status = %d \n\r",FUNCTION,(status=-1)); return  status;
	}

//-----------------XScuTimer_CfgInitialize----------------------//
	status = XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,ConfigPtr->BaseAddr);
	if(status){
		xil_printf("%s :XScuTimer_CfgInitialize error exit Status = %d \n\r",FUNCTION,(status)); return status;
	}

//-----------------XScuTimer_LoadTimer-------------------------//
	XScuTimer_LoadTimer(TimerInstancePtr, TIMER_LOAD_VALUE/num);
	XScuTimer_Start(TimerInstancePtr);
	xil_printf("%s :init OK  \n\r",FUNCTION);
	return status;
}
static void  delayed(int count,int Timer)
{
	int  timer_value;
	SystemTimetInit(Timer);
	for(;count > 0;count--){
		while(1){
			timer_value = XScuTimer_GetCounterValue(TimerInstancePtr);
			if(timer_value == 0){
				XScuTimer_RestartTimer(TimerInstancePtr); //装载初始值重新开始计数
				break ;
			 }
	   }
	}
	XScuTimer_Stop(TimerInstancePtr);
}

仅为个人笔记参考。

你可能感兴趣的:(ZYNQ,笔记)