7.2 - 定时器之计算脉冲宽度实验

1 实验任务

本实验任务是通过CPU私有定时器来计算按键按下的时间长短。

2 系统框图

参见7.1。

3 硬件设计

参见7.1。

4 软件设计

4.1 注意事项

  1. 定时器是递减计数的,需要考虑StartCount<EndCount的情况。

4.2 工程源码

/***************************** Include Files ********************************/

#include <stdio.h>
#include "xparameters.h"
#include "xgpiops.h"
#include "xscutimer.h"
/************************** Constant Definitions ****************************/

#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID
#define TIMER_DEVICE_ID		XPAR_XSCUTIMER_0_DEVICE_ID

#define PS_KEY0_GPIO_PIN	50

#define TIMER_LOAD_VALUE	0xFFFFFFFF

#define TIMER_CLK_FREQ		XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2

/**************************** Type Definitions ******************************/

/***************** Macros (Inline Functions) Definitions ********************/

/************************** Function Prototypes *****************************/

int  GpioInit(XGpioPs* GpioInstPtr);
int  TimerInit(XScuTimer* TimerInstPtr);

/************************** Variable Definitions ****************************/

XGpioPs   GpioInst;
XScuTimer TimerInst;

u32 StartCount = 0;
u32 EndCount = 0;

/****************************************************************************/

int main()
{
	//
	int Status;
    u32 KeyValue;
    u32 CountDiff;
    u32 TimerClkFreq = TIMER_CLK_FREQ;
    float PressedTime;

	//
	Status = GpioInit(&GpioInst);
	if (Status == XST_FAILURE) {
		printf("Error : gpio initialization failed.\n");
		return XST_FAILURE;
	}

	//
	Status = TimerInit(&TimerInst);
	if (Status == XST_FAILURE) {
		printf("Error : timer initialization failed.\n");
		return XST_FAILURE;
	}

	// 启动定时器
	XScuTimer_Start(&TimerInst);

	//
	printf("Press the key to start timing...\n");

	//
	while(1)
	{
	    // 等待按键按下
	    while (1) {
	    	KeyValue = XGpioPs_ReadPin(&GpioInst, PS_KEY0_GPIO_PIN);
	        if (KeyValue == 0) { // 按键按下为低电平
	        	StartCount = XScuTimer_GetCounterValue(&TimerInst);
	            printf("Key pressed, timing started.\n");
	            break;
	        }
	    }

	    // 等待按键释放
	    while (1) {
	    	KeyValue = XGpioPs_ReadPin(&GpioInst, PS_KEY0_GPIO_PIN);
	        if (KeyValue == 1) { // 按键释放为高电平
	            EndCount = XScuTimer_GetCounterValue(&TimerInst);
	            printf("Key released, timing stopped.\n");
	            break;
	        }
	    }

	    // 计算差值
	    if (EndCount > StartCount) {
	    	printf("EndCount > StartCount.\n");
	    	CountDiff = (0xFFFFFFFF - EndCount) + StartCount + 1; // 注意:定时器会溢出
	    }
	    else {
	    	printf("EndCount < StartCount.\n");
	    	CountDiff = StartCount - EndCount; // 注意:定时器是递减的
	    }

	    //
	    printf("Key pressed for %lu clock cycles.\n", CountDiff);

	    // 转换为时间
	    PressedTime = (float)CountDiff / TimerClkFreq;
	    printf("Key pressed for %.3f seconds.\n", PressedTime);
	}

	//
	return 0;
}

/****************************************************************************/

int GpioInit(XGpioPs* GpioInstPtr)
{
	//
	int Status;
	XGpioPs_Config* GpioPsConfigPtr;

	//
	GpioPsConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	Status = XGpioPs_CfgInitialize(GpioInstPtr, GpioPsConfigPtr, GpioPsConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	// 设置输入
	XGpioPs_SetDirectionPin(GpioInstPtr, PS_KEY0_GPIO_PIN, 0);

	//
	return XST_SUCCESS;
}

/****************************************************************************/

int  TimerInit(XScuTimer* TimerInstPtr)
{
	//
	int Status;
	XScuTimer_Config* TimerConfigPtr;

	//
	TimerConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
	Status = XScuTimer_CfgInitialize(TimerInstPtr, TimerConfigPtr, TimerConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	// 自动加载
	XScuTimer_EnableAutoReload(TimerInstPtr);

	// 加载初值
	XScuTimer_LoadTimer(TimerInstPtr, TIMER_LOAD_VALUE);

	//
	return XST_SUCCESS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值