| 
              【程序】#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);
 }
 }
 }
 }
 
 
 |