1 实验任务
本实验任务是通过CPU私有定时器来计算按键按下的时间长短。
2 系统框图
参见7.1。
3 硬件设计
参见7.1。
4 软件设计
4.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;
}