<big><br /> PC按键具有如下特性:当按下某个键时,系统立即响应,如果未松手,则键值会重复出现,直到松手时才停止。如附图所示的Windows键盘属性设置,有两个重要的按键参数:重复延迟和重复率。重复延迟是指从按下键不松手开始,到第1次键值重复开始时的时间间隔;重复率是指以后连续重复的速率,每两次重复之间的时间间隔越短重复越快。<br /><img src="http://bbs.21ic.com/upfiles/img/200712/2007125162742447.jpg"><br /><br /> 以下程序是系统节拍定时器SysTick的一个应用,利用其定时中断扫描按键KEY的输入,并模拟出PC按键的重复特性,结果通过UART输出。在程序里,SysTick设置的定时中断周期是10ms,可自动地消除按键抖动,同时还能保证每秒100次的按键采样速率。重复延时参数是KEY_DELAY,即按下KEY后若不松手则等待10×KEY_DELAY毫秒后开始重复。重复速率参数是KEY_SPEED,即开始重复后每两次重复之间的时间间隔为10×KEY_SPEED毫秒。<br /><br /> 在SysTick中断服务函数SysTick_ISR( )里,采用状态处理的方法,实现了预定的功能,并没有出现任何无谓的等待。<br /></big><br /><br />#include <hw_types.h><br />#include <hw_memmap.h><br />#include <hw_ints.h><br />#include <hw_sysctl.h><br />#include <hw_gpio.h><br />#include <hw_uart.h><br />#include <interrupt.h><br />#include <systick.h><br />#include <sysctl.h><br />#include <gpio.h><br />#include <uart.h><br /><br />// 将较长的标识符定义成较短的形式<br />#define SysCtlPeriEnable SysCtlPeripheralEnable<br />#define SysCtlPeriDisable SysCtlPeripheralDisable<br />#define GPIOPinTypeIn GPIOPinTypeGPIOInput<br />#define GPIOPinTypeOut GPIOPinTypeGPIOOutput<br />#define GPIOPinTypeOD GPIOPinTypeGPIOOutputOD<br /><br />// 定义KEY<br />#define KEY_PERIPH SYSCTL_PERIPH_GPIOD<br />#define KEY_PORT GPIO_PORTD_BASE<br />#define KEY_PIN GPIO_PIN_1<br /><br />// 设置KEY重复延迟和重复速率参数<br />#define KEY_DELAY 75<br />#define KEY_SPEED 10<br /><br />// 定义按键缓冲区<br />char KEY_Buf = '\0';<br /><br />// UART初始化<br />void uartInit(void)<br />{<br /> SysCtlPeriEnable(SYSCTL_PERIPH_UART0); // 使能UART模块<br /> SysCtlPeriEnable(SYSCTL_PERIPH_GPIOA); // 使能RX/TX所在的GPIO端口<br /><br /> GPIOPinTypeUART(GPIO_PORTA_BASE, // 配置RX/TX所在管脚为<br /> GPIO_PIN_0 | GPIO_PIN_1); // UART收发功能<br /><br /> UARTConfigSet(UART0_BASE, // 配置UART端口<br /> 9600, // 波特率:9600<br /> UART_CONFIG_WLEN_8 | // 数据位:8<br /> UART_CONFIG_STOP_ONE | // 停止位:1<br /> UART_CONFIG_PAR_NONE); // 校验位:无<br /><br /> UARTEnable(UART0_BASE); // 使能UART端口<br />}<br /><br />// 主函数(程序入口)<br />int main(void)<br />{<br /> SysCtlClockSet(SYSCTL_USE_OSC | // 系统时钟设置<br /> SYSCTL_OSC_MAIN | // 采用主振荡器<br /> SYSCTL_XTAL_6MHZ | // 外接6MHz晶振<br /> SYSCTL_SYSDIV_1); // 不分频<br /><br /> uartInit(); // UART初始化<br /><br /> SysCtlPeriEnable(KEY_PERIPH); // 使能KEY1所在的GPIO端口<br /> GPIOPinTypeIn(KEY_PORT, KEY_PIN); // 设置KEY1所在管脚为输出<br /><br /> SysTickPeriodSet(10 * (SysCtlClockGet() / 1000)); // 设置SysTick周期,定时10ms<br /> SysTickIntEnable(); // 使能SysTick中断<br /> IntMasterEnable(); // 使能处理器中断<br /> SysTickEnable(); // 使能SysTick计数器<br /><br /> for (;;)<br /> {<br /> if (KEY_Buf != '\0') // 如果KEY缓冲区不空<br /> {<br /> UARTCharPut(UART0_BASE, KEY_Buf); // 显示KEY值<br /> KEY_Buf = '\0'; // 清空KEY缓冲区<br /> }<br /> }<br />}<br /><br />// SysTick计数器的中断服务函数<br />void SysTick_ISR(void)<br />{<br /> static tBoolean bStatus = false; // KEY状态:false松开,true按下<br /> static unsigned short usDelayCnt = 0; // 重复延时计数器<br /> static unsigned short usSpeedCnt = 0; // 重复速率计数器<br /><br /> if (bStatus) // 如果原先KEY是按下的<br /> {<br /> if (GPIOPinRead(KEY_PORT, KEY_PIN) == 0x00) // 如果KEY仍为按下状态<br /> {<br /> if (usDelayCnt == 0) // 如果重复延时已经结束<br /> {<br /> if (--usSpeedCnt == 0) // 执行重复动作<br /> {<br /> usSpeedCnt = KEY_SPEED;<br /> KEY_Buf = 'K';<br /> }<br /> }<br /> else<br /> {<br /> usDelayCnt--;<br /> }<br /> }<br /> else // 如果KEY已松开<br /> {<br /> bStatus = false;<br /> }<br /> }<br /> else // 如果原先KEY是松开的<br /> {<br /> if (GPIOPinRead(KEY_PORT, KEY_PIN) == 0x00) // 如果KEY按下<br /> {<br /> bStatus = true;<br /> KEY_Buf = 'K';<br /> usDelayCnt = KEY_DELAY;<br /> usSpeedCnt = KEY_SPEED;<br /> }<br /> }<br />}<br /> |
|