我现在的任务是做一个8*8的矩阵键盘,制PCB版之前,我用电路板搭了一个3*3的矩阵键盘来模拟一下,设置PA0、PA1、PA2为PP输出,设置P3、P4、P5下拉输入。大多数的芯片内部上拉或下拉电阻都是弱上拉或弱下拉,stm32f103的内部也一样,内部上拉或下拉的电阻阻值约为40K,这样可以方便外部调整,但是,在作为一些通讯引脚时,可能会出现上电时数据不稳定的问题,如I2C通讯,解决的办法是在外部在加上一个较强的上拉或下拉即可。具体程序如下:
#include <stm32f10x.h>
#include "usart.h"
void KeyBoard_Init(void)//按键初始化
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);
GPIO_ResetBits(GPIOA,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
void Delay(u32 nCount)//延时函数
{
for(; nCount != 0; nCount--);
}
u8 KeyDown(void)
{
if((GPIO_ReadInputData(GPIOA)&0xff)!=0x07)//判断是否有键按下
{
return 1;//keydown
}
else return 0;
}
u8 Read_KeyValue(void)
{
unsigned int KeyValue=0;
GPIO_SetBits(GPIOA,GPIO_Pin_0);
GPIO_ResetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2);//此时PA0读取的数据是0x01
switch(GPIO_ReadInputData(GPIOA)&0xff)
{
case 0x11:KeyValue='A';break;//此时PA口去的数据是0x11,其余读数与此原理相同
case 0x21:KeyValue='B';break;
case 0x41:KeyValue='C';break;
default: break;
}
GPIO_SetBits(GPIOA,GPIO_Pin_1);
GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_2);
switch(GPIO_ReadInputData(GPIOA)&0xff)
{
case 0x12:KeyValue='D';break;
case 0x22:KeyValue='E';break;
case 0x42:KeyValue='F';break;
default: break;
}
GPIO_SetBits(GPIOA,GPIO_Pin_2);
GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1);
switch(GPIO_ReadInputData(GPIOA)&0xff)
{
case 0x14:KeyValue='G';break;
case 0x24:KeyValue='H';break;
case 0x44:KeyValue='I';break;
default: break;
}
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);
GPIO_ResetBits(GPIOA,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
while((GPIO_ReadInputData(GPIOA)&0xff)!=0x07);
printf("%c",KeyValue);
return KeyValue;
}
int ScanKeyBoard(void)
{
if(KeyDown()
{
Delay(0xffff);//软件去抖。按键抖动时间一般为5-10ms,延时以20ms为宜
if(KeyDown())
{
return Read_KeyValue();//按键扫描
}
else
{
printf("nothing");
}
}
return 0;
}
int main(void)
{
u32 i=100;
SystemInit();
usart_Configuration();
KeyBoard_Init();
Delay(i);
while(1)
{
ScanKeyBoard();
Delay(500);
}
}
用串口观察实验结果还可以,但个别时候会同时打印出按键字母和“nothing”,我感觉可能是焊接的问题,元器件接触不良很有可能造成这种结果,具体等PCB板回来再测量。
若以上程序或说明有什么不对的地方,还望指正,谢谢。