基于ZYNQ-7000开发板的调试系列(5)

程序中断(2)

这一部分是基于基于ZYNQ-7000开发板的调试系列(4)继续展开的,主要的部分是需要两个定时器开启中断开始。这一部分主要是需要使用TTC,完成2组流水灯的同时工作,两组的频率也不一致。TTC Block Diagram
[参考自ZYNQ7000 TRM (Page.245-249)]
TTC可以完成的工作比较多,其实TTC的使用是可以控制GPIO的占空比。这个的最简单的使用例程就是做一个呼吸灯。但是需要使用到PL的PWM,这里就先不涉及这一部分的内容了。
[参考自ZYNQ进阶之路8–PS端实现EMIO TTC PWM输出(与PL端PWM联合使用)]

1. 修改Block

1. 修改ZYNQ7 Processing System

ZYNQ7 Processing System
其实这里主要就是需要把TTC0和TTC1打开,这里提供的EMIO是可以向外输出波形的,这里可以并不需要,所以这里可以不用向外提供接口。具体的Diagram图大概是这个样子的。Diagram
然后这里就没有其他需要修改的部分了,这里生成Bitstream即可。

2. 编写PS程序

这一部分的程序编写其实和上一部分几乎是一致的,和上一部分最大的不同就是TTC的使能和控制。
其中,引入必须引入的库:

#include "xttcps.h"

然后是关于TTC的函数:

  1. 初始化
XTtcPs_Config *XTtcPs_LookupConfig(
	u16 DeviceId
);
s32 XTtcPs_CfgInitialize(
	XTtcPs *InstancePtr,
    XTtcPs_Config * ConfigPtr, 
    u32 EffectiveAddr
);
  1. 定时器配置
s32 XTtcPs_SetOptions(
	XTtcPs *InstancePtr, 
	u32 Options
); //关于TTC的模式配置
void XTtcPs_CalcIntervalFromFreq(
	XTtcPs *InstancePtr, 
	u32 Freq,
	XInterval *Interval, 
	u8 *Prescaler
); //通过用户给定的频率计算分频和间隔的数值,并赋值到指定的地址上
void XTtcPs_SetInterval(
	XTtcPs *InstancePtr;
	XInterval interval
); // 该函数实质上就是往寄存器里写入值
void XTtcPs_SetPrescaler(
	XTtcPs *InstancePtr, 
	u8 PrescalerValue
); // 该函数按照指定的分频向寄存器内写入值
void XTtcPs_EnableInterrupts(
	XTtcPs *InstancePtr, 
	u32 InterruptMask
); // 该函数实质上就是往寄存器里写入值,使能TTC中断

定时器开始

XTtcPs_Start(
	XTtcPs *InstancePtr
); // 该函数实质上就是往寄存器里写入值,开始计数

中断内函数

u32 XTtcPs_GetInterruptStatus(
	XTtcPs *InstancePtr
); // 检测是否已经触发了中断
void XTtcPs_ClearInterruptStatus(
	XTtcPs *InstancePtr,
	u32 statusEvent
); // 如果触发中断,该部分解除中断

其余部分和上一部分几乎一致。程序如下:

#include "xparameters.h"
#include "xgpio.h"
#include "xgpiops.h"

#include "xttcps.h"
#include "xstatus.h"
#include "xscugic.h"
#include "xil_exception.h"

#define PS_GIC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID

#define LEDG1_INTR_ID XPAR_XTTCPS_0_INTR
#define LEDG2_INTR_ID XPAR_XTTCPS_3_INTR

#define LED1_INTR_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID
#define LED2_INTR_DEVICE_ID XPAR_XTTCPS_3_DEVICE_ID

#define LED1_FREQ_HZ	2
#define LED2_FREQ_HZ 	3

#define PL_GPIO_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define PS_GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID

#define PL_LED_CHANNEL 1
#define PL_KEY_CHANNEL 2

#define PS_BANK XGPIOPS_BANK0

#define PL_LED0 0x01
#define PL_LED1 0x02
#define PL_LED2 0x04
#define PL_LED3 0x08
#define PL_LED4 0x10

#define PS_LED0 0x09
#define PS_LED1 0x00

typedef struct {
	u32 OutputHz;	/* Output frequency */
	XInterval Interval;	/* Interval value */
	u8 Prescaler;	/* Prescaler value */
	u16 Options;	/* Option settings */
} TmrCntrSetup;

volatile u8 led_status = 0x00;
volatile u8 state1;
volatile u8 state2;

volatile u8 plLed;
volatile u8 psLed;

XGpio plGpio;
XGpioPs psGpio;

XTtcPs psTimer1;
XTtcPs psTimer2;

XScuGic	psGic;

static TmrCntrSetup timer1Setup = {LED1_FREQ_HZ, 0, 0, 0};
static TmrCntrSetup timer2Setup = {LED2_FREQ_HZ, 0, 0, 0};


int init();
void run();
int init_Gpio();
int init_Exti();
int init_Gpio_Pl();
int init_Gpio_Ps();
int init_Exti_Timer1();
int init_Exti_Timer2();
int init_Exti_Gic();

void psIntrTimer1Handler(void*);
void psIntrTimer2Handler(void*);

// 0
int main(){
	int status;
	status = init();
	if(status != XST_SUCCESS) return XST_FAILURE;
	run();
	return 0;
}

// 1
int init(){
	int status;
	status = init_Gpio();
	if(status != XST_SUCCESS) return XST_FAILURE;
	status = init_Exti();
	if(status != XST_SUCCESS) return XST_FAILURE;
	return XST_SUCCESS;
}

void run(){
	XTtcPs_Start(&psTimer1);
	XTtcPs_Start(&psTimer2);
	while(1){
		switch(state1){
		case 1: {
			plLed = (plLed & 0x10) + 0x0E;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED0, 0x01);
		}break;
		case 2: {
			plLed = (plLed & 0x10) + 0x0D;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED0, 0x01);
		}break;
		case 3: {
			plLed = (plLed & 0x10) + 0x0B;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED0, 0x01);
		}break;
		case 4: {
			plLed = (plLed & 0x10) + 0x07;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED0, 0x01);
		}break;
		case 0: {
			plLed = (plLed & 0x10) + 0x0F;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED0, 0x00);
		}break;
		default:{
			plLed = (plLed & 0x10) + 0x0F;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED1, 0x01);
		}
		}
		switch(state2){
		case 0:{
			plLed = (plLed & 0x0F) + 0x00;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED1, 0x01);
		} break;
		case 1:{
			plLed = (plLed & 0x0F) + 0x10;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED1, 0x00);
		} break;
		default:{
			plLed = (plLed & 0x0F) + 0x10;
			XGpio_DiscreteWrite(&plGpio, PL_LED_CHANNEL, plLed);
			XGpioPs_WritePin(&psGpio, PS_LED1, 0x01);
		}
		}
	}
}

// 2
int init_Gpio(){
	int status;
	status = init_Gpio_Pl();
	if(status != XST_SUCCESS) return XST_FAILURE;
	status = init_Gpio_Ps();
	if(status != XST_SUCCESS) return XST_FAILURE;

	// PL
	XGpio_SetDataDirection(&plGpio, PL_LED_CHANNEL, 0x00);
	XGpio_SetDataDirection(&plGpio, PL_KEY_CHANNEL, 0x01);

	// PS
	XGpioPs_SetDirection(&psGpio, PS_BANK, 0x201);
	XGpioPs_SetOutputEnable(&psGpio, PS_BANK, 0x201);

	return XST_SUCCESS;
}

int init_Exti(){
	int status;
	TmrCntrSetup *t1;
	TmrCntrSetup *t2;
	status = init_Exti_Timer1();
	if(status != XST_SUCCESS) return XST_FAILURE;
	status = init_Exti_Timer2();
	if(status != XST_SUCCESS) return XST_FAILURE;
	status = init_Exti_Gic();
	if(status != XST_SUCCESS) return XST_FAILURE;

	// Timer //
	t1 = &timer1Setup;
	t2 = &timer2Setup;
	t1->Options |= (XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE);
	t2->Options |= (XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE);

	XTtcPs_SetOptions(&psTimer1, t1->Options);
	XTtcPs_CalcIntervalFromFreq(&psTimer1, t1->OutputHz, &(t1->Interval), &(t1->Prescaler));
	XTtcPs_SetInterval(&psTimer1, t1->Interval);
	XTtcPs_SetPrescaler(&psTimer1, t1->Prescaler);
	XTtcPs_EnableInterrupts(&psTimer1, XTTCPS_IXR_INTERVAL_MASK);

	XTtcPs_SetOptions(&psTimer2, t2->Options);
	XTtcPs_CalcIntervalFromFreq(&psTimer2, t2->OutputHz, &(t2->Interval), &(t2->Prescaler));
	XTtcPs_SetInterval(&psTimer2, t2->Interval);
	XTtcPs_SetPrescaler(&psTimer2, t2->Prescaler);
	XTtcPs_EnableInterrupts(&psTimer2, XTTCPS_IXR_INTERVAL_MASK);

	// Gic
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				&psGic);
	status = XScuGic_Connect(&psGic, LEDG1_INTR_ID,
						(Xil_ExceptionHandler)psIntrTimer1Handler,
						(void *)&psTimer1);
	if(status != XST_SUCCESS) return XST_FAILURE;
	XScuGic_Enable(&psGic, LEDG1_INTR_ID);

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				&psGic);
	status = XScuGic_Connect(&psGic, LEDG2_INTR_ID,
						(Xil_ExceptionHandler)psIntrTimer2Handler,
						(void *)&psTimer2);
	if(status != XST_SUCCESS) return XST_FAILURE;
	XScuGic_Enable(&psGic, LEDG2_INTR_ID);

	Xil_ExceptionEnable();
	return XST_SUCCESS;

}

// 3
int init_Gpio_Pl(){
	XGpio_Config *xGpioCfg;
	xGpioCfg = XGpio_LookupConfig(PL_GPIO_DEVICE_ID);
	if(xGpioCfg == (XGpio_Config *)NULL) return XST_FAILURE;
	return XGpio_CfgInitialize(&plGpio, xGpioCfg, xGpioCfg->BaseAddress);
}

int init_Gpio_Ps(){
	XGpioPs_Config *xGpioCfg;
	xGpioCfg = XGpioPs_LookupConfig(PS_GPIO_DEVICE_ID);
	if(xGpioCfg == (XGpioPs_Config *)NULL) return XST_FAILURE;
	return XGpioPs_CfgInitialize(&psGpio, xGpioCfg, xGpioCfg->BaseAddr);
}

int init_Exti_Timer1(){
	XTtcPs_Config *xGpioCfg;
	xGpioCfg = XTtcPs_LookupConfig(LED1_INTR_DEVICE_ID);
	if(xGpioCfg == (XTtcPs_Config *)NULL) return XST_FAILURE;
	return XTtcPs_CfgInitialize(&psTimer1, xGpioCfg, xGpioCfg->BaseAddress);
} 

int init_Exti_Timer2(){
	XTtcPs_Config *xGpioCfg;
	xGpioCfg = XTtcPs_LookupConfig(LED2_INTR_DEVICE_ID);
	if(xGpioCfg == (XTtcPs_Config *)NULL) return XST_FAILURE;
	return XTtcPs_CfgInitialize(&psTimer2, xGpioCfg, xGpioCfg->BaseAddress);
} 

int init_Exti_Gic(){
	XScuGic_Config *xGpioCfg;
	xGpioCfg = XScuGic_LookupConfig(PS_GIC_DEVICE_ID);
	if(xGpioCfg == (XScuGic_Config *)NULL) return XST_FAILURE;
	return XScuGic_CfgInitialize(&psGic, xGpioCfg, xGpioCfg->CpuBaseAddress);
} 

void psIntrTimer1Handler(void *ref){
	u32 statusEvent;

	statusEvent = XTtcPs_GetInterruptStatus(&psTimer1);
	XTtcPs_ClearInterruptStatus(&psTimer1, statusEvent);

	if(0 != (XTTCPS_IXR_INTERVAL_MASK & statusEvent)){
		switch(state1){
		case 0: state1 = 1; break;
		case 1: state1 = 2; break;
		case 2: state1 = 3; break;
		case 3: state1 = 4; break;
		case 4: state1 = 0; break;
		default: state1 = 0;
		}
	}
}

void psIntrTimer2Handler(void *ref){
	u32 statusEvent;

	statusEvent = XTtcPs_GetInterruptStatus(&psTimer2);
	XTtcPs_ClearInterruptStatus(&psTimer2, statusEvent);

	if(0 != (XTTCPS_IXR_INTERVAL_MASK & statusEvent)){
		switch(state2){
		case 0: state2 = 1; break;
		case 1: state2 = 0; break;
		default: state2 = 0;
		}
	}
}

该部分代码和之前没有太大的出入,完成流水灯部分代码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值