我使用的引脚为:PA2-7
电路图片:(仅供电路图参考)
思路:(行列扫描法),起始可以将2,3,4设置为上拉输入(下拉输入),5,6,7设置为输出低电平(输出高点平)当按键按下的时候,电平会由1->0,这样就可以检测到电平的变化,从而获得对应的按键接口值
首先,使能你对应的时钟,然后需要把你需要的引脚置零
RCC->APB2ENR|=1<<2;
GPIOA->CRL&=0XFF; // 清零
端口配置低寄存器将其配置为输入上拉的模式,即(1000)
GPIOA->CRL|=0X33388800;
注意的是你设置为1000的时候,你不能确定是上拉还是下拉,所以你需要进行ODR操作
GPIOA->ODR|=1<<2; //上拉
GPIOA->ODR|=1<<3;
GPIOA->ODR|=1<<4;
当你需要下拉的时候将1换成0即可,并左移至向相应的引脚
然后将5,6,7设置为低电平输出
PAout(5) = 0;
PAout(6) = 0; //设置为低电平
PAout(7) = 0;
然后进行检测,当2,3,4其中任何一个检测到低电平的时候,进行相应的返回值(若是二,则知证明是在第一行,三则是在第二行.....)
if(PAin(2) == 0||PAin(3) == 0||PAin(4) == 0)
{
delay_ms(10);
if(PAin(2) == 0)
{
i = 1;
}
if(PAin(3) == 0)
{
i = 2;
}
if(PAin(4) == 0)
{
i = 3;
}
}
这样就得知了按键是在哪一行,然后接下里就是寻找是在哪一列,将输入和输出进行反转
GPIOA->CRL&=0X000000FF; // 清零//将pa2,3,4设置为输出,5,6,7设置为输入
GPIOA->CRL|=0X88833300;
GPIOA->ODR|=1<<5; //上拉
GPIOA->ODR|=1<<6;
GPIOA->ODR|=1<<7;
PAout(2) = 0;
PAout(3) = 0; //设置为低电平
PAout(4) = 0;
if(PAin(5) == 0||PAin(6) == 0||PAin(7) == 0)
{
delay_ms(10);
if(PAin(5) == 0)
{
j = 1;
}
if(PAin(6) == 0)
{
j = 2;
}
if(PAin(7) == 0)
{
j = 3;
}
}
最后在借助i和j判断是在哪个位置
if(i == 1)
{
if(j == 1)
{
return 1;
}
if(j == 2)
{
return 2;
}
if(j == 3)
{
return 3;
}
}
if(i == 2)
{
if(j == 1)
{
return 4;
}
if(j == 2)
{
return 5;
}
if(j == 3)
{
return 6;
}
}
if(i == 3)
{
if(j == 1)
{
return 7;
}
if(j == 2)
{
return 8;
}
if(j == 3)
{
return 9;
}
}
if(i==0&&j==0)
return 0;
在主函数中进行接受相应的字符,然后在串口打印相应的值
u8 t;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口初始化为9600
while(1)
{
t = KEY_Init();
switch(t)
{
case '1':
delay_ms(1000);
printf("1\r\n");
break;
case '2':
delay_ms(1000);
printf("2\r\n");
break;
case '3':
delay_ms(1000);
printf("3\r\n");
break;
case '4':
delay_ms(1000);
printf("4\r\n");
break;
case '5':
delay_ms(1000);
printf("5\r\n");
break;
case '6':
delay_ms(1000);
printf("6\r\n");
break;
case '7':
delay_ms(1000);
printf("7\r\n");
break;
case '8':
delay_ms(1000);
printf("8\r\n");
break;
case '9':
delay_ms(1000);
printf("9\r\n");
break;
case '0':
delay_ms(1000);
printf("没有按键输入\r\n");
break;
}
}