ZYNQ 使用AXI TIMER的定时和PWM

前言

最近在学习ZYNQ的PS端,目前是裸机阶段,学习CPU的私有定时器时,发现每个核似乎只有一个,搜索了一下IP库,发现有个AXI TIMER,并且有PWM功能,于是照着官方例程配置了一下,在这里记录一下。 PL+PS的架构确实方便啊,ARM用C开发,还可以上Linux,想要什么定制化的东西还可以用FPGA。

1、ZYNQ配置


一个AXI TIMER有两个通道,这里我全部使用了,并且使能了中断,添加模块的时候发现还有一个PWM引脚,于是我配了一个PL的IO上去,都测试一下。

2、SDK代码

2.1 定时器配置

需要关注的点都写到注释里了

#include "xparameters.h"
#include "xtmrctr.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"

/*正确配置ZYNQ后,XPAR_AXI_TIMER_0_DEVICE_ID、XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR可以在xparameters.h中找到*/
#define SCUGIC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID 			//通用中断 ID
#define AXI_TIMER_DEVICE_ID		XPAR_AXI_TIMER_0_DEVICE_ID				//AXI_Timer设备ID
#define AXI_TIMER_IRPT_INTR		XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR	//AXI TIMER 中断号

XTmrCtr		xTmrCtr_Inst;	//AXI Timer驱动示例
XScuGic 	xScuGic_Inst;	//中断控制器驱动程序实例

//AXI TIMER模块内有两个定时器,这里我更愿意叫做每个AXI TIMER的不同通道,编号为0-1
#define AXI_TIMER_CHANNEL_1		0
#define AXI_TIMER_CHANNEL_2		1

//定义是否测试PWM
#define AXI_TIMER_PWM_TEST_SW	1

//定时器周期(微秒为单位)
#define AXI_TIMER_PERIOD_US			10000
//PWM高电平的持续时间(微秒为单位)
#define AXI_TIMER_PWM_HIGH_TIME_US	5000

//定时器中断回调
void xTmrCtr_Int_Handler(void *CallBackRef, u8 TmrCtrNumber)
{
	xil_printf("AXI Timer Int! Channel:%d\n",TmrCtrNumber+1);
}

//定时的微秒数转寄存器值
//AXI TIMER是倒计时,如果想定时1MS,那么寄存器中要写入:最大值-1MS
//AXI TIMER的时钟为50M,1US为50个Tick
u32 xTmr_US_To_RegValue(u32 US)
{
	u32 Value;

	Value = 50*US;

	return 0xFFFFFFFF - Value;
}

//定时的微秒数转纳秒
u32 xTmr_US_To_NS(u32 US)
{
	return US*1000;
}

//AXITIMER初始化
int xTmrCtr_Init(XTmrCtr *xTmrCtr_Ptr,u32 DeviceId)
{
	int Status,DutyCycle;

	//初始化AXI_TIMER 0
	Status = XTmrCtr_Initialize(xTmrCtr_Ptr, DeviceId);
	if(Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	//自检:两个定时器
	Status = XTmrCtr_SelfTest(xTmrCtr_Ptr, 2-1);
	if(Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	//设置中断回调函数
	XTmrCtr_SetHandler(xTmrCtr_Ptr,xTmrCtr_Int_Handler,xTmrCtr_Ptr);

	//定时器1中断计数
	XTmrCtr_SetResetValue(xTmrCtr_Ptr,AXI_TIMER_CHANNEL_1,xTmr_US_To_RegValue(AXI_TIMER_PERIOD_US));
	//定时器2中断计数
	XTmrCtr_SetResetValue(xTmrCtr_Ptr,AXI_TIMER_CHANNEL_2,xTmr_US_To_RegValue(AXI_TIMER_PERIOD_US));

	//定时器中断打开
	XTmrCtr_SetOptions(xTmrCtr_Ptr, AXI_TIMER_CHANNEL_1, XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION);
	XTmrCtr_SetOptions(xTmrCtr_Ptr, AXI_TIMER_CHANNEL_2, XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION);

	//测试PWM的话,额外配置一下PWM功能
	#if AXI_TIMER_PWM_TEST_SW
		DutyCycle = XTmrCtr_PwmConfigure(xTmrCtr_Ptr, xTmr_US_To_NS(AXI_TIMER_PERIOD_US),xTmr_US_To_NS(AXI_TIMER_PWM_HIGH_TIME_US));
		//打印占空比
		xil_printf("AXI Timer PWM DutyCycle:%d%!\n",DutyCycle);
	#endif

	return XST_SUCCESS;
}

2.2 通用中断配置

这没什么说的。

//通用中断初始化
int xScuGic_Init(XScuGic *ScuGic_Ptr,XTmrCtr *xTmrCtr_Ptr)
{
	int Status;
	XScuGic_Config *intc_cfg_ptr;
	intc_cfg_ptr = XScuGic_LookupConfig(SCUGIC_DEVICE_ID);
	if(intc_cfg_ptr == NULL)
	{
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(ScuGic_Ptr, intc_cfg_ptr,intc_cfg_ptr->CpuBaseAddress);
	if(Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	//设置并打开中断异常处理功能
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler, ScuGic_Ptr);
	Xil_ExceptionEnable();

	//设置定时器中断
	XScuGic_Connect(ScuGic_Ptr, AXI_TIMER_IRPT_INTR,(Xil_ExceptionHandler)XTmrCtr_InterruptHandler, (void *)xTmrCtr_Ptr);

	//使能 GIC中的定时器中断
	XScuGic_Enable(ScuGic_Ptr, AXI_TIMER_IRPT_INTR);

	return XST_SUCCESS;

}

2.2 PWM功能

代码在定时器初始化中。

3、实际使用

int main()
{
	u32 Status;

	xil_printf("AXI Timer Test!\n");

	//定时器初始化
	Status = xTmrCtr_Init(&xTmrCtr_Inst,AXI_TIMER_DEVICE_ID);
	if(Status != XST_SUCCESS)
	{
		xil_printf("AXI Timer Init Error!\n");
	}

	//通用中断初始化
	Status = xScuGic_Init(&xScuGic_Inst,&xTmrCtr_Inst);
	if(Status != XST_SUCCESS)
	{
		xil_printf("ScuGic Init Error!\n");
	}

	//AXI TIMER的两个通道都开始工作
	XTmrCtr_Start(&xTmrCtr_Inst,AXI_TIMER_CHANNEL_1);
	XTmrCtr_Start(&xTmrCtr_Inst,AXI_TIMER_CHANNEL_2);

	//AXI_TIMER_PWM_TEST_SW为1时,启用PWM
	#if AXI_TIMER_PWM_TEST_SW
		XTmrCtr_PwmDisable(&xTmrCtr_Inst);
		XTmrCtr_PwmEnable(&xTmrCtr_Inst);
	#endif

	while(1);

	return 0;
}

4、总结

在中断回调里,会打印AXI TIMER的哪个通道产生了中断,更改了几个定时时间,功能正常。
PWM功能,利用示波器点了一下配置的PL引脚,更改了几个占空比,波形正常。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值