| 
              【程序】#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 in, out;
 uint8_t col, row;
 uint8_t i, keycode;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
 
 // 默认输入/输出模式
 in.GPIO_Mode = GPIO_Mode_IPU;
 out.GPIO_Mode = GPIO_Mode_Out_PP;
 out.GPIO_Speed = GPIO_Speed_2MHz;
 
 // PB8~15用作数码管显示,为输出
 out.GPIO_Pin = 0xff00;
 GPIO_Init(GPIOB, &out);
 
 display(0xbf); // 默认显示'-'
 while (1)
 {
 // 第一步:和行扫描法一样,先将行线作为输出线, 列线作为输入线
 out.GPIO_Pin = 0x0f;
 GPIO_Init(GPIOA, &out);
 in.GPIO_Pin = 0xf0;
 GPIO_Init(GPIOA, &in);
 GPIO_ResetBits(GPIOA, 0x0f); // 行线全输出0
 col = GPIO_ReadInputData(GPIOA) & 0xf0; // 读取列线的值
 
 // 按键消抖
 if (col != 0xf0)
 {
 delay();
 col = GPIO_ReadInputData(GPIOA) & 0xf0;
 if (col != 0xf0)
 {
 // 第二步:从列线输出全0信号,再读取行线的输入值
 out.GPIO_Pin = 0xf0;
 GPIO_Init(GPIOA, &out);
 in.GPIO_Pin = 0x0f;
 GPIO_Init(GPIOA, &in);
 GPIO_ResetBits(GPIOA, 0xf0);
 row = GPIO_ReadInputData(GPIOA) & 0x0f;
 
 // 行线有非1值的情况下才继续
 // 防止出现按下了6显示的却是2的错误情况
 if (row != 0x0f)
 {
 // 第三步:计算键码
 row = ~row & 0x0f;
 col = ~col >> 4 & 0x0f;
 keycode = 0;
 for (i = 0; i < 4; i++)
 {
 if (row & 1)
 {
 keycode = i * 4;
 break;
 }
 row >>= 1;
 }
 for (i = 0; i < 4; i++)
 {
 if (col & 1)
 {
 keycode += i;
 break;
 }
 col >>= 1;
 }
 display(table[keycode]);
 
 while ((GPIO_ReadInputData(GPIOA) & 0x0f) != 0x0f);
 }
 }
 }
 }
 }
 
 
 |