ZYNQ学习笔记——9_定时器中断实验

9_定时器中断实验

实现功能:4个LED流水灯闪烁,200ms的延时
PYNQ_Z2开发板

实验过程

定时器计数器的计算以及中断处理函数的编写解释均写在代码中

配置:

  • GPIO初始化
  • 定时器初始化
  • 定时器中断初始化
  • 写中断处理函数

正定原子视频最后讲解了在线调试操作

代码

#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xscutimer.h"
#include "xscugic.h"

//实现功能:4个LED流水灯闪烁,200ms的延时

#define GPIOPS_ID			XPAR_XGPIOPS_0_DEVICE_ID //PS 端 GPIO 器件 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

#define TIMER_LOAD_VALUE	0x3DFCBE6
/*  想要延时200ms: 时钟为1/2的CPU时钟,即为650/2=325MHz。
    先计算时钟周期:1s/325M=3.077ns
    200ms对应数字:200ms/3.077ns =64998375 = 0x3DFCBE7  ;结果-1(从0开始)   */

//PS可以直接操作的管教是54个,MIO0-MIO53;所以EMIO的扩展引脚编号就是54往后排序从GPIO0_tri_io 0 依次往后进行编号
#define LED0			54
#define LED1			55
#define LED2			56
#define LED3			57

void mio_init();
void timer_init(XScuTimer *TimerInstancePtr,u16 TimerDeviceId);
void timer_intr_init(XScuGic *IntcInstancePtr,XScuTimer *TimerInstancePtr,u16 TimerIntrId);
void timer_intr_handler(void *CallBackRef);

XScuTimer TimerInstance;	/* Cortex A9 Scu Private Timer Instance */

XGpioPs gpiops_inst;	/* The driver instance for GPIO Device. */
XScuGic IntcInstance;		/* Interrupt Controller Instance */

int main()
{
	//MIO初始化
	mio_init();
	//定时器初始化
	timer_init(&TimerInstance,TIMER_DEVICE_ID);
	//定时器中断初始化
	timer_intr_init(&IntcInstance,&TimerInstance,TIMER_IRPT_INTR);

	XScuTimer_Start(&TimerInstance);

	printf("TIMER TEST !\n\r");
	while(1);
	return 0;
}

//GPIO初始化
void mio_init()
{
	XGpioPs_Config * gpiops_cfg_ptr;
	//根据器件的ID,查找器件的配置信息
	gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
	//初始化GPIO驱动
	XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
	//设置LED为输出  ;把GPIO的方向设置为输出 (0:输入/ 1:输出)
	XGpioPs_SetDirectionPin(&gpiops_inst, LED0, 1);
	XGpioPs_SetDirectionPin(&gpiops_inst, LED1, 1);
	XGpioPs_SetDirectionPin(&gpiops_inst, LED2, 1);
	XGpioPs_SetDirectionPin(&gpiops_inst, LED3, 1);
	//设置LED输出使能(0:关闭/ 1:打开)
	XGpioPs_SetOutputEnablePin(&gpiops_inst, LED0, 1);
	XGpioPs_SetOutputEnablePin(&gpiops_inst, LED1, 1);
	XGpioPs_SetOutputEnablePin(&gpiops_inst, LED2, 1);
	XGpioPs_SetOutputEnablePin(&gpiops_inst, LED3, 1);

}


//定时器初始化
void timer_init(XScuTimer *TimerInstancePtr,u16 TimerDeviceId)
{
	XScuTimer_Config *ConfigPtr;
	//初始化私有定时器
	ConfigPtr = XScuTimer_LookupConfig(TimerDeviceId);
	XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,
						ConfigPtr->BaseAddr);
	//配置计数器初始值
	XScuTimer_LoadTimer(TimerInstancePtr, TIMER_LOAD_VALUE);
	//使能自动装载模式
	XScuTimer_EnableAutoReload(TimerInstancePtr);

}

//定时器中断初始化
void timer_intr_init(XScuGic *IntcInstancePtr,XScuTimer *TimerInstancePtr,u16 TimerIntrId)
{
	XScuGic_Config *IntcConfig;

	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
						IntcConfig->CpuBaseAddress);
	//中断异常处理
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
					(Xil_ExceptionHandler)XScuGic_InterruptHandler,
					IntcInstancePtr);
	Xil_ExceptionEnable();
	XScuTimer_EnableInterrupt(TimerInstancePtr);
	//设置定时器的中断处理函数
	XScuGic_Connect(IntcInstancePtr, TimerIntrId,
					(Xil_ExceptionHandler)timer_intr_handler,
					(void *)TimerInstancePtr);
	//使能中断控制器
	XScuGic_Enable(IntcInstancePtr, TimerIntrId);
	//使能定时器中断
	XScuTimer_EnableInterrupt(TimerInstancePtr);

}

//中断处理函数
void timer_intr_handler(void *CallBackRef){
	static char led_status=0x01;
	XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
	//进入中断之后清除中断
	if(XScuTimer_IsExpired(TimerInstancePtr))
	{
		//向MIO引脚写入高低电平,只看最低位是0还是1
		XGpioPs_WritePin(&gpiops_inst,LED0,led_status);
		XGpioPs_WritePin(&gpiops_inst,LED1,led_status>>1);
		XGpioPs_WritePin(&gpiops_inst,LED2,led_status>>2);
		XGpioPs_WritePin(&gpiops_inst,LED3,led_status>>3);
		XScuTimer_ClearInterruptStatus(TimerInstancePtr);
		led_status = led_status<<1;

		if(led_status == 0X10)
			led_status =0x01;
		printf("led_status=%d\n",led_status);

/*led_status的状态:
 * 均转化成二进制计算
* 0x01(0000_0001)->0x02(0000_0010)->0x04(0000_0100)->0x08(0000_1000)->{0x10(0001_0000)}->0x01
 *  按此循环
 *  串口打印的led_status值为:1,2,4,8 循环
 */
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值