说明: 开发软件 :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里面的定时器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;
}
代码流程框图:
延时器代码实现
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);
}
仅为个人笔记参考。