第五课--使用定时器实现中断(1)

0,前言

使用定时器实现中断。这里通过PS端的EMIO进行使用计数器,然后再定时产生中断。本来听得很头疼,后来自己想了想,画了个图,再结合前面讲的,就觉得清楚了很多。这里分享下这张图。
在这里插入图片描述

1,代码分析

这里的FPGA代码很简单,C代码由于之前已经都学过了,这里只是将两个模块的函数简单修改即可。这里只贴代码。
在这之前先总结一个问题。就是我在使能EMIO的时候,只要了一个GPIO口。前面介绍过有0-53个MIO,因此EMIO是从54开始的。但是当我将55这个编号作为使能信号时,时钟信号却总是不能拉低。而将其值修改为54的时候,就可以很好地使能了。因此这里的EMIO使用是有他的顺序的。
其次就是在定义status的时候。发现有两个地址。因此返回值总是错误的。代码原本是我在main函数中定义了一个status,在初始化GPIO的时候又定义了一次。于是就出现了上述返回错误的问题。因此在代码中,我将其定义在函数之外,不在任何一个函数中定义这个变量,问题就被解决了。
代码分享
Verilog代码

module interrupt_10_50ms(
    input sclk,
    input rst,
    output intr10ms,
    output intr50ms
    );
    
    parameter INTR10MS_END = 24'd1999999;
    parameter INTR50MS_END = 24'd9999999;
    parameter PULER_W      = 8'd199;
    reg         intr10ms_flag,intr50ms_flag;
    reg    [31:0]     intr10ms_cnt;
    reg    [31:0]     intr50ms_cnt;
    
    assign intr10ms = intr10ms_flag;
    assign intr50ms = intr50ms_flag;
    always @ (posedge sclk)begin 
    if(rst == 1'b1) begin
        intr10ms_cnt <=  'd0;
    end 
    else if(intr10ms_cnt == INTR10MS_END)begin 
        intr10ms_cnt <= 'd0;
    end 
    else begin 
        intr10ms_cnt <= intr10ms_cnt + 1'b1;
    end 
    end 

    always @ (posedge sclk)begin 
    if(rst == 1'b1) begin
        intr50ms_cnt <=  'd0;
    end 
    else if(intr50ms_cnt == INTR50MS_END)begin 
        intr50ms_cnt <= 'd0;
    end 
    else begin 
        intr50ms_cnt <= intr50ms_cnt + 1'b1;
    end 
    end 

    always @ (posedge sclk)
    begin
    	if(rst == 1'b1 )
    		intr10ms_flag <= 1'b0;
    	else 
    		if(intr10ms_cnt == PULER_W)
    			intr10ms_flag <= 1'b0;
    		else 
    			if(intr10ms_cnt == INTR10MS_END)
    				intr10ms_flag <= 1'b1;
    			else 
    				intr10ms_flag <= intr10ms_flag;
    end

    always @ (posedge sclk)
    begin
        if(rst == 1'b1 )
            intr50ms_flag <= 1'b0;
        else 
            if(intr50ms_cnt == PULER_W)
                intr50ms_flag <= 1'b0;
            else 
                if(intr50ms_cnt == INTR50MS_END)
                    intr50ms_flag <= 1'b1;
                else 
                    intr50ms_flag <= intr50ms_flag;
    end
    
endmodule

C代码。代码虽然有点长,但是原理很清楚。就是

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"		//import gpio
#include "xparameters.h"
#include "xscugic.h"

#define GPIO_DEV_ID XPAR_PS7_GPIO_0_DEVICE_ID 			//redefine device id
#define GIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID				//redefine GIC id

#define F2P_INTR0_ID 61
#define GPIO0 54
XGpioPs GpioPs;//实例化一个对象,将对其进行配置
XGpioPs_Config *GpioPsCfgPtr;
static XScuGic ScuGic;
static XScuGic_Config * ScuGicCfgPtr;
int status;

void f2pIntr0Handler(void * callbackref);
int initGpio();
int initHwIntr();

int main()
{
	initGpio();//initial GPIO
	if(status != XST_SUCCESS){
	        return status ;
	}
    initHwIntr();
    if(status != XST_SUCCESS){
    		return status ;
    	}
    XGpioPs_WritePin(&GpioPs,GPIO0,(u32)0x01);
    while(1){

    }
}
//initial gpio
int initGpio(){
	GpioPsCfgPtr = XGpioPs_LookupConfig(GPIO_DEV_ID);
	status =  XGpioPs_CfgInitialize(&GpioPs,GpioPsCfgPtr,GpioPsCfgPtr->BaseAddr);
	if(status != XST_SUCCESS){
			return status ;
		}
	XGpioPs_SetDirectionPin(&GpioPs,GPIO0,0x01);
	XGpioPs_SetOutputEnablePin(&GpioPs,GPIO0,0x01);
	return status;
}
//hw callback function id = 61
void f2pIntr0Handler(void * callbackref){
	printf("interrupt id = 61 success!\n\r");
}

//initial gic & hardware intr
int initHwIntr(){
	Xil_ExceptionInit();//打开系统异常
	ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
	status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
	if(status != XST_SUCCESS){
			return status ;
		}
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
	status = XScuGic_Connect(&ScuGic,F2P_INTR0_ID,(Xil_ExceptionHandler)f2pIntr0Handler,&ScuGic);
	if(status != XST_SUCCESS){
			return status ;
		}
	XScuGic_Enable(&ScuGic,F2P_INTR0_ID);
	Xil_ExceptionEnable();
	return XST_SUCCESS;
}

打印的结果是正确的。有时候可能会遇见一些莫名其妙的问题。不要着急,关掉再打开试试有可能问题就解决了!!!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值