ZYNQ笔记(九):定时器中断

版本:Vivado2020.2(Vitis)

任务:使用定时器 (私有定时器) 中断 实现 LED(PS端) 定时1s亮灭翻转

目录

一、介绍

二、硬件设计

三、软件设计

四、效果


一、介绍

Zynq系列是Xilinx(现为AMD)推出的集成了ARM Cortex-A9双核处理器和FPGA的可编程SoC器件。在Zynq中,定时器是重要的外设模块,用于时间测量、延时控制和周期性中断触发等。

Zynq主要有以下几种定时器:

  1. 私有定时器(Private Timer) - 每个ARM核都有一个私有定时器

  2. 全局定时器(Global Timer) - 双核共享的64位定时器

  3. 看门狗定时器(Watchdog Timer、WDT) - 用于系统监控和复位

  4. 三重定时器计数器(TTC) - FPGA侧提供的定时器

像 PS 端延时可以用定时器中断方式进行操作,以让cpu执行其他重要操作。

二、硬件设计

ZYNQ 的配置使用到了 MIO(LED灯)、UART(用于Debug)、DDR(存储器),跟之前的工程案例相比没有额外的特殊配置,下面这幅图是CPU的工作频率,保持默认666.666MHz,定时器驱动时钟是其二分之一,也就是333.333MHz(后面会用到)

最后整体 bd 设计部分如图所示:设计检查、Generate Output Products、 Create HDL Wrapper、(管脚约束、Gnerate Bitstream、(无PL端设计这两部忽略))、Export Hardware(不用包含比特流文件)、启动Vitis

三、软件设计

可以打开官方提供的私有定时器的示例工程,这里可以选定时器中断的示例工程,方便在设计时进行对照参考。

cs 复制代码
#include "xparameters.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xscutimer.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "sleep.h"

//===========================自定义宏=========================//

#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID 		//宏定义GPIO器件ID
#define MIO_LED  	        7						 		//宏定义LED管脚(PS端LED,根据开发板设值,这里对应GPIO MIO 7)

#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID	//宏定义中断控制器(GIC)ID
#define TIMER_DEVICE_ID		XPAR_XSCUTIMER_0_DEVICE_ID      //宏定义TIMER器件ID
#define TIMER_IRPT_INTR		XPAR_SCUTIMER_INTR				//宏定义TIMER中断号(中断ID)

#define TIMER_LOAD_VALUE	0x13DE4354	//定时器计数值(定时器驱动时钟333.333MHz为CPU时钟(默认666.66MHz)一半,周期约3ns,定时1s计数333_333_333 -1 次)

//===========================实例化===========================//

XGpioPs Gpio;		//GPIO示例
XScuGic Intc;		//中断控制器实例
XScuTimer Timer;	//定时器实例

//=======================函数、变量声明=======================//

static void Gpio_Init();        					//GPIO初始化
static void Timer_Intr_Init();  					//定时器中断初始化
static void LED_blink();        					//LED闪烁测试
static void Timer_IntrHandler(void *CallBackRef);	//定时器中断处理函数
static void Setup_Intr_System(XScuGic *intr,  XScuTimer *timer, u16 timer_intr_id);	//建立中断系统

//===========================主函数===========================//

int main()
{
	xil_printf("SCU Timer Interrupt Test! \r\n");
	Gpio_Init(); 		//GPIO初始化
	LED_blink(); 		//LED闪烁测试
	Timer_Intr_Init();  //定时器中断初始化

	while(1)
	return 0;
}

//=====================定时器中断处理函数=====================//
// @param CallBackRef  用户自定义回调参数(对应TIMER实例指针)

void Timer_IntrHandler(void *CallBackRef)
{
	static int led_state = 0;
	//将回调参数转为TIMER实例指针,用于操作硬件(例规范化设计)
	XScuTimer *TimerInstPtr = (XScuTimer *) CallBackRef;

    //打印Debug信息
	xil_printf("Interrupt Detected! \r\n");
	//清除定时器中断标志位
	XScuTimer_ClearInterruptStatus(TimerInstPtr);
	//翻转LED状态值
	led_state = ~led_state;
	//写数据到GPIO引脚(PS端LED)
	XGpioPs_WritePin(&Gpio, MIO_LED, led_state);

}

//=========================GPIO初始化========================//
void Gpio_Init()
{
	//定义器件ID(指针类型)
	XGpioPs_Config * ConfigPtr;
	//根据器件ID,查找器件配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	//初始化GPIO的驱动
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	//GPIO方向设置(0输入/1输出)
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED,  1);
	//设置输出使能(1使能)
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED, 1);
}

//======================定时器中断初始化======================//
void Timer_Intr_Init()
{
	//定义器件ID(指针类型)
	XScuTimer_Config *ConfigPtr;
	//根据器件ID,查找器件配置信息
	ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
	//初始化定时器的驱动
	XScuTimer_CfgInitialize(&Timer, ConfigPtr,ConfigPtr->BaseAddr);
	//(可选)定时器自检
	int Status = XScuTimer_SelfTest(&Timer);
	if (Status != XST_SUCCESS) { xil_printf("Timer Self Test Error! \r\n"); }

	//建立中断系统(调用函数)
	Setup_Intr_System(&Intc,  &Timer, TIMER_IRPT_INTR);

	//加载计数值(计数上限)
	XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);
	//使能自动加载模式(计完自动加载计数值,不启用计完一次结束)
	XScuTimer_EnableAutoReload(&Timer);
	//启动定时器
	XScuTimer_Start(&Timer);
}

//=======================建立中断系统=======================//
/* 建立中断系统,UART接收到数据时产生中断
 * @param intr			是指向 XScuGic驱动实例的指针
 * @param timer 		是指向 XScuTimer驱动实例的指针
 * @param timer_intr_id	是TIMER中断ID
 */
void Setup_Intr_System(XScuGic *intr,  XScuTimer *timer, u16 timer_intr_id)
{
    //定义中断控制器配置信息(指针)
	XScuGic_Config * IntcConfig;
	//根据中断控制器ID,查找GIC配置信息
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	//初始化中断控制器驱动
	XScuGic_CfgInitialize(intr, IntcConfig, IntcConfig->CpuBaseAddress);
    //设置中断异常处理功能
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
			(void *) intr);
	//使能处理器中断
	Xil_ExceptionEnable();
	//关联中断处理函数
	XScuGic_Connect(intr, timer_intr_id,
				(Xil_ExceptionHandler) Timer_IntrHandler,
				(void *) timer);
	//使能GIC中的定时器中断
	XScuGic_Enable(intr, timer_intr_id);
	//使能定时器中断
	XScuTimer_EnableInterrupt(timer);
}

//========================LED闪烁测试========================//
void LED_blink()
{
	for(int i=0; i<3; i++)//闪烁3次
	{
		//向GPIO写1 、延时200ms、写0、延时
		XGpioPs_WritePin(&Gpio, MIO_LED, 1);  usleep(200000);
		XGpioPs_WritePin(&Gpio, MIO_LED, 0);  usleep(200000);
	}
}

四、效果

上板后会先打印测试信息,然后LED灯快速闪烁3次(说明MIO配置无误),此后每秒定时器会产生中断,并将LED的状态翻转,效果为每两秒闪烁一次

相关推荐
梁朝辉2 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者3 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间4 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious4 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng8 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计9 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试一、基本概念
嵌入式硬件·通信与接口协议
wuyk5551 天前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机
☆cwlulu1 天前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu
lzqrzpt1 天前
LED驱动电源选型标准与工程应用技术要点解析
python·单片机·嵌入式硬件·物联网