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 循环
*/
}
}