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