第三个任务,实现键盘扫描,并通过串口通讯显示被按下的键位。
在上一节,了解了矩阵键盘的大致工作原理,那么应该怎样去实现显示被按下的按钮的键位呢?通过行列扫描 ,即拉高某一行或者某一列的电平,然后去扫描全部列或者全部行。
例如将所有列对应的针脚设置为推挽输出,剩下的全部行设置为上拉输入,然后假设我们按下了图上所示的7号按钮。程序应该怎么检测这一事件呢?先检测每一列,因为当按钮被按下后,某一列的电平肯定会变为0,那么我们可以知道是哪一列有按钮被按下了,此时我们需要知道是这一列中的哪一行的按钮被按下。那么通过下面的扫描函数可以得到返回值“1011”即0x0B,也就是第二行被按下;
uint8_t key_row[1]={0xff};//给key_row赋初值
key_row[0] = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)<<3;//第一行的结果左移3位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)<<2;//第二行的结果左移2位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)<<1;//第三行的结果左移1位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15);
然后我们可以通过一个switch语句来判断扫描函数返回的数值所代表的是哪一行被按下,此时通过这个函数将返回3;
if(key_row[0]!=0x0f){//如果返回值不为1111
delay_ms(10);//延迟10毫秒,消抖
if(key_row[0]!=0x0f){//判断有按钮被按下
switch(key_row[0]){
case 0x07://返回0111,第一行被按下,返回1
return 1;
case 0x0b://返回1011,第二行被按下,返回2
return 2;
case 0x0d://返回1101,第三行被按下,返回3
return 3;
case 0x0e://返回1110,第四行被按下,返回4
return 4;
default://默认返回0
return 0;
}
}else return 0;//没有被按下,只是机械抖动,返回0
}else return 0;//没有被按下,返回0
那么结合起来的思路就是,我们拉低每一列的电平,然后检查有没有哪一列的返回值不等于0,这是扫描列的思路;同理也可以通过扫描行来实现,具体代码如下:
[zhedie]
//key16.c
#include "key16.h"
#include "delay.h"
uint8_t key_row[1]={0xff};
void key_init(){
GPIO_InitTypeDef GPIO_InitStruture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
//定义PD8、PD9、PD10、PD11为推挽输出
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruture);
//定义PB12、PB13、PB14、PB15为上拉输入 分别定义为四行
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_Init(GPIOB,&GPIO_InitStruture);
}
char key_row_scan(){//扫描列
key_row[0] = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)<<3;
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)<<2;
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)<<1;
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15);
if(key_row[0]!=0x0f){
delay_ms(10);
if(key_row[0]!=0x0f){//判断有按钮被按下
switch(key_row[0]){
case 0x07://返回0111,第一列被按下,返回1
return 1;
case 0x0b://返回1011,第二列被按下,返回2
return 2;
case 0x0d://返回1101,第三列被按下,返回3
return 3;
case 0x0e://返回1110,第四列被按下,返回4
return 4;
default://默认返回0
return 0;
}
}else return 0;
}else return 0;
}
char key_scan(){
char key=0;//存放按键号
char row_num=0;
//第一行
KEY_CLO0_OUT_LOW;//拉低,扫描
if((row_num=key_row_scan())!=0){
while(key_row_scan()!=0){
key=0+row_num;
}
}
KEY_CLO0_OUT_HIGH;//重新拉高
//第二行
KEY_CLO1_OUT_LOW;
if((row_num=key_row_scan())!=0){
while(key_row_scan()!=0){
key=4+row_num;
}
}
KEY_CLO1_OUT_HIGH;
//第三行
KEY_CLO2_OUT_LOW;
if((row_num=key_row_scan())!=0){
while(key_row_scan()!=0){
key=8+row_num;
}
}
KEY_CLO2_OUT_HIGH;
//第四行
KEY_CLO3_OUT_LOW;
if((row_num=key_row_scan())!=0){
while(key_row_scan()!=0){
key=12+row_num;
}
}
KEY_CLO3_OUT_HIGH;
return key;
}
[/zhedie]
有了上面的代码后,在main.c中添加引用,调用函数进行判断,并通过串口输出结果:
具体代码:[zhedie]
//key16.h
#ifndef _KEY16_H
#define _KEY16_H
#include "sys.h"
#include "stm32f10x.h"
#include <string.h>
#define KEY_row0_Pin GPIO_Pin_8
#define KEY_row1_Pin GPIO_Pin_9
#define KEY_row2_Pin GPIO_Pin_10
#define KEY_row3_Pin GPIO_Pin_11
void key_init();
char key_scan();
char key_row_scan();
#define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOD,GPIO_Pin_8,Bit_RESET)
#define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOD,GPIO_Pin_9,Bit_RESET)
#define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOD,GPIO_Pin_10,Bit_RESET)
#define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOD,GPIO_Pin_11,Bit_RESET)
#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOD,GPIO_Pin_8,Bit_SET)
#define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOD,GPIO_Pin_9,Bit_SET)
#define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOD,GPIO_Pin_10,Bit_SET)
#define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOD,GPIO_Pin_11,Bit_SET)
#endif
//led.c
#include "led.h"
#include "stm32f10x.h"
#include "delay.h"
void led_init(){
GPIO_InitTypeDef GPIO_InitStruture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //??PB???
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //??PE???
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruture);
GPIO_SetBits(GPIOB,GPIO_Pin_9);
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruture);
GPIO_SetBits(GPIOE,GPIO_Pin_0);
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruture);
GPIO_SetBits(GPIOE,GPIO_Pin_1);
}
void Led_shine(char key_num){//定义了闪烁函数,根据key_num的值LED1闪烁
int t;
switch(key_num){
case 1:
for(t=1;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 2:
for(t=2;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 3:
for(t=3;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 4:
for(t=4;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 5:
for(t=5;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 6:
for(t=6;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 7:
for(t=7;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 8:
for(t=8;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 9:
for(t=9;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 10:
for(t=10;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 11:
for(t=11;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 12:
for(t=12;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 13:
for(t=13;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 14:
for(t=14;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 15:
for(t=15;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
case 16:
for(t=16;t>0;t--){
LED1off;
delay_ms(250);
LED1on;
delay_ms(250);
}
break;
}
}
//led.h
#ifndef _LED_H
#define _LED_H
#include "sys.h"
#define LED1on GPIO_SetBits(GPIOE,GPIO_Pin_1)
#define LED1off GPIO_ResetBits(GPIOE,GPIO_Pin_1)
#define LED2 PEout(0)
#define LED3 PBout(9)
void led_init();
void Led_shine(char key_num);//声明了Led_shine函数
#endif
//main.c
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key16.h"
#include "stdio.h"
#include "usart.h"
int main(void)
{
char key_num;
int t;
key_init();
led_init();
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
while(1)
{
key_num=key_scan();
if(key_num>0&&key_num<17){
printf("Button %d Pressed!\r\n",key_num);
printf("LED shine %d times!\r\n",key_num);
printf("<====This is a Line====>\r\n\r\n");
Led_shine(key_num);
}
}
}
[/zhedie]
Comments | NOTHING
Warning: Undefined variable $return_smiles in /www/wwwroot/blog/wp-content/themes/sakura-3.4.0/functions.php on line 1096