一、ZYNQ定時器簡介
????????每個Cortex-A9處理器都有自己的專用32位定時器和32位看門狗定時器。兩個處理器共享一個全局64位定時器。這些計時器的時鐘始終為CPU頻率(CPU_3x2x)的1/2。在系統級,有一個24位看門狗定時器和兩個16位三重定時器/計數器。系統看門狗定時器時鐘在1/4或1/6的CPU頻率(CPU_1x),或可以通過外部信號從MIO引腳或從PL時鐘。兩個三重定時器/計數器總是時鐘1/4或1/6的CPU頻率(CPU_1x),用于計算信號脈沖的寬度一個MIO引腳或從PL。
如下是系統框圖。由此可以發現該2處理器有系統看門狗定時器、有CPU看門狗定時器、CPU私有定時器、全局時鐘定時器、兩個三從定時器。這些定時器都可以觸發中斷。本次實驗任務用到的是CPU處理器的私有定時器觸發中斷。
????????系統框圖。和前面的mio控制led的系統差不多,只是用到了定時器中斷,因此項目工程在原有的項目基礎上另存為后修改一下即可。
二、開發流程
1、?在我們原來的工程MIO LED上不需要修改硬件設計。
2、如過你是拷貝或者復制的原項目到新的目錄下需要修改路徑。第一種可以刪掉SDK文件然后重新建立工程寫代碼。第二種如果你不想刪掉原代碼,只想在此基礎上上修改,就需要修改板級知識包的路徑。方法如下
第二種方法請點擊此處。
3、復制我們的代碼進main.c里面。這里只需要按照你板子的原理圖修改一下MIO引腳即可。代碼不過解釋,想了解的可以查看小梅哥或則正點原子的SOC開發手冊。
/** main.c** Created on: 2025年9月1日* Author: 32652*/#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xscugic.h"
#include "XScuTimer.h"#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR//PS端LED
#define MIO7_LED 7
//我們想要計時的值
#define TIMER_LOAD_VALUE 0x3F94067//333.333MHzXGpioPs_Config *ConfigPtr_gpio;
XGpioPs Gpio;
XScuTimer_Config *ConfigPtr_timer;
XScuTimer timer;
XScuGic_Config *ConfigPtr_inter;
XScuGic inter;
int state=0;int mio_init(XGpioPs_Config *ConfigPtr_gpio,XGpioPs *Gpio)
{//初始化GPIO的驅動ConfigPtr_gpio = XGpioPs_LookupConfig(GPIO_DEVICE_ID);XGpioPs_CfgInitialize(Gpio, ConfigPtr_gpio,ConfigPtr_gpio->BaseAddr);//把GPIO引腳設置為輸出(0:輸入,1:輸出)XGpioPs_SetDirectionPin(Gpio, MIO7_LED, 1);//打開輸出使能XGpioPs_SetOutputEnablePin(Gpio, MIO7_LED, 1);//寫數據到GPIO引腳,由原理圖可知設置為1時候點亮。初始時點亮。XGpioPs_WritePin(Gpio, MIO7_LED, 0x1);return XST_SUCCESS;
}int timer_init(XScuTimer_Config *ConfigPtr_timer,XScuTimer *timer)
{int Status;//初始化定時器ConfigPtr_timer = XScuTimer_LookupConfig(TIMER_DEVICE_ID);Status = XScuTimer_CfgInitialize(timer, ConfigPtr_timer,ConfigPtr_timer->BaseAddr);if (Status != XST_SUCCESS) {return XST_FAILURE;}//自檢驗Status = XScuTimer_SelfTest(timer);if (Status != XST_SUCCESS) {return XST_FAILURE;}//使能自動裝載模式。XScuTimer_EnableAutoReload(timer);//設置定時器時間XScuTimer_LoadTimer(timer, TIMER_LOAD_VALUE);return XST_SUCCESS;
}void timer_interr_handle(void *CallBackRef)
{XScuTimer *timer = (XScuTimer *) CallBackRef;//XScuTimer_IsExpired這個函數是判斷定時器有沒有過期。if (XScuTimer_IsExpired(timer)){XScuTimer_ClearInterruptStatus(timer);if(state){state=0;XGpioPs_WritePin(&Gpio, MIO7_LED, 0x0);}else{state=1;XGpioPs_WritePin(&Gpio, MIO7_LED, 0x1);}}}int timer_sys_init(XScuGic_Config *ConfigPtr_inter,XScuGic *inter)
{int Status;ConfigPtr_inter = XScuGic_LookupConfig(INTC_DEVICE_ID);if (NULL == ConfigPtr_inter) {return XST_FAILURE;}Status = XScuGic_CfgInitialize(inter, ConfigPtr_inter,ConfigPtr_inter->CpuBaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}Status = XScuGic_Connect(inter, TIMER_IRPT_INTR,(Xil_ExceptionHandler)timer_interr_handle,(void *)&timer);if (Status != XST_SUCCESS) {return Status;}//使能中斷設備。XScuGic_Enable(inter, TIMER_IRPT_INTR);//使能中斷模式XScuTimer_EnableInterrupt(&timer);//處理ARM異常,中斷程序必須有的三個函數Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,inter);Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);//啟動定時器。中斷系統配置完成再使能。XScuTimer_Start(&timer);return 0;
}int main()
{printf("gpio_mio_test\n");mio_init(ConfigPtr_gpio,&Gpio);timer_init(ConfigPtr_timer,&timer);timer_sys_init(ConfigPtr_inter,&inter);XScuTimer_Start(&timer);while(1);return 0;
}
4、試驗成功。