硬件介绍
本次实验的硬件依旧时实验二所需的实验器材,只是本次需要将矩阵键盘的八个接口都利用上,且矩阵键盘的电路图如下图所示
然后这里我们的电源模块也需要使用RXD TXD接口。
硬件连接
这里我们的矩阵键盘连接的对应端口如下
其次,我们的电源模块中的RXD需连接在单片机的TXD上,电源模块中的TXD需连接在单片机的RXD上。
程序书写
程序思路
首先我们依旧涉及到了按键的输入,所以首先想到的也是需要消抖
其次,这里我们需要判断时哪一个按键被按下了,确定按键按下的思路:令PD8 PD9 PD10 PD11为上拉输入 PB12 PB13 PB14 PB15为浮空输入,然后按下按键后扫描每一列,判断如果是1111则这一行有按键被按下,若按键被按下再通过判断是0111 1011 1101 1110来判断是这一列的第几行被按下,从而来准确判断出是哪一个键被按下。
key.c key.h的书写
听过上面的思路我们写出了如下程序:
#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);
//定义PB12、PB13、PB14、PB15为推挽输出
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruture);
//定义PD8、PD9、PD10、PD11为上拉输入 分别定义为四行
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOD,&GPIO_InitStruture);
}
//如果为1,代表没有按键被按下,如果为0,代表有按键被按下
char KEY_ROW_SCAN(){
KEY_ROW[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;//读取PD8的状态并左移三位
KEY_ROW[0] = KEY_ROW[0]|GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2;读取PD8的状态并左移两位
KEY_ROW[0] = KEY_ROW[0]|GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1;读取PD8的状态并左移一位
KEY_ROW[0] = KEY_ROW[0]|GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11);
if(KEY_ROW[0] !=0x0f)//不是1111,代表肯定有一个0
{
delay_ms(10);
if(KEY_ROW[0] !=0x0f){
//0111 1011 1101 1110
switch(KEY_ROW[0]){
case 0x07: //0111 第一行
return 1;
case 0x0b: //1011 第二行
return 2;
case 0x0d: //1101 第三行
return 3;
case 0x0e: //1110 第四行
return 4;
default:
return 0;
}
}else return 0;
}else return 0;
}
char KEY_SCAN(){
char key=0;//存放那个按键被按下(按键号)
char row_num=0;//存放行扫描结果(哪一个被按下)
//扫描第0列
KEY_CLO0_OUT_LOW;
if( (row_num = KEY_ROW_SCAN())!=0){
while((row_num=KEY_ROW_SCAN())!=0){//按键消抖
key=0+row_num;
}
}
KEY_CLO0_OUT_HIGH;
//扫描第1列
KEY_CLO1_OUT_LOW;
if( (row_num = KEY_ROW_SCAN())!=0){
while((row_num = KEY_ROW_SCAN())!=0){
key=4+row_num;
}
}
KEY_CLO1_OUT_HIGH;
//扫描第2列
KEY_CLO2_OUT_LOW;
if( (row_num = KEY_ROW_SCAN())!=0){
while((row_num = KEY_ROW_SCAN())!=0){
key=8+row_num;
}
}
KEY_CLO2_OUT_HIGH;
//扫描第3列
KEY_CLO3_OUT_LOW;
if( (row_num = KEY_ROW_SCAN())!=0){
while((row_num = KEY_ROW_SCAN())!=0){
key=12+row_num;
}
}
KEY_CLO3_OUT_HIGH;
return key;
}
注意这里对较新内容的理解
在key.c中使用的部分变量与函数在key.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_ROW_SCAN();
char KEY_SCAN();
#define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET)
#define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET)
#define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)
#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET)
#define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET)
#define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET)
#define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)
#endif
最后效果
这里写完上面的程序之后我得到的效果便是,十六个键的按下与否都能读取,且将十六个键从上到下从左到右依次定义为了1–16.(由于不能上传视频,所以只能口述了)