【程序】 #include <stm32f10x.h> // 共阳数码管段码表 unsigned char table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf}; // 用于按键延时 void delay(void) { uint16_t i; for (i = 0; i < 20000; i++); } // 在数码管上显示指定段码 void display(uint8_t n) { GPIO_ResetBits(GPIOB, 0xff00); GPIO_SetBits(GPIOB, n << 8); } int main(void) { GPIO_InitTypeDef init; uint8_t i, temp; uint8_t keycode; // 同时开启PA和PB的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // PB8~15用作数码管显示,为输出 init.GPIO_Mode = GPIO_Mode_Out_PP; init.GPIO_Pin = 0xff00; init.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &init); // PA0~7用作矩阵键盘 init.GPIO_Pin = 0x0f; GPIO_Init(GPIOA, &init); // 行线为输出 init.GPIO_Mode = GPIO_Mode_IPU; // 没有信号输入时,视为输入了高电平 init.GPIO_Pin = 0xf0; GPIO_Init(GPIOA, &init); // 列线为输入 display(0xbf); // 默认显示'-' while (1) { GPIO_ResetBits(GPIOA, 0x0f); // 行线输出0 temp = GPIO_ReadInputData(GPIOA) & 0xf0; // 读列线。如果按键没有按下,则没有信号输入(引脚悬空);如果有按键按下,则输入的是按键对面输出的0 // 如果读出来列线中有为0的位,则表明有按键按下 if (temp != 0xf0) { // 按键消抖 delay(); temp = GPIO_ReadInputData(GPIOA) & 0xf0; if (temp != 0xf0) { // 如果确实按下了按键 // 行扫描 for (i = 0; i < 4; i++) { GPIO_SetBits(GPIOA, 0x0f); // 行线全设为1 GPIO_ResetBits(GPIOA, 1 << i); // 将要检查的行设为0 temp = GPIO_ReadInputData(GPIOA) & 0xf0; // 按同样的方法读列线 if (temp != 0xf0) // 如果不全为1, 则表明该行有按键按下 { // 根据temp和i的值计算键码 temp = ~temp >> 4 & 0x0f; keycode = i * 4; if (temp == 8) keycode += 3; else keycode += temp >> 1; // keycode为最终计算出来的键码, 取值范围是0~15 // 可在这里进行按键处理 // 显示键码并退出行扫描 display(table[keycode]); break; } } // 等待按键释放 while ((GPIO_ReadInputData(GPIOA) & 0xf0) != 0xf0); } } } }
|