}
在这里IO口的配置没什么问题,行线是配置为推挽输出,列线都是配置为上拉输入。
void keypads_linescan_IPU()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // KEY_5,KEY_6,KEY_7 行线
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_8);
}
void keypads_rowscan_IPU()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |GPIO_Pin_6 | GPIO_Pin_7; // KEY_1,KEY_2,KEY_3,KEY_4 列线
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
void keypads_linescan_Out_PP()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // KEY_5,KEY_6,KEY_7 行线
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_8);
}
void keypads_rowscan_Out_PP()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |GPIO_Pin_6 | GPIO_Pin_7; // KEY_1,KEY_2,KEY_3,KEY_4 列线
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
然后就是行列分别配置推挽输出和下拉输入。
int key_line = 0;
char key_val;
char keypads_scan()
{
key_val = '$';
keypads_linescan_IPU();
keypads_rowscan_Out_PP();
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0){
keypads_linescan_Out_PP();
keypads_rowscan_IPU();
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 0){
key_line = 1;
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0){
key_line = 2;
GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6) == 0){
key_line = 3;
GPIO_SetBits(GPIOA, GPIO_Pin_6);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == 0){
key_line = 4;
GPIO_SetBits(GPIOA, GPIO_Pin_7);
}
else key_line = 0;
switch(key_line)
{
case 1:key_val = '1';break;
case 2:key_val = '2';break;
case 3:key_val = '3';break;
case 4:key_val = 'A';break;
}
key_line = 0;
keypads_linescan_IPU();
keypads_rowscan_Out_PP();
}
else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0){
keypads_linescan_Out_PP();
keypads_rowscan_IPU();
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 0){
key_line = 1;
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0){
key_line = 2;
GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6) == 0){
key_line = 3;
GPIO_SetBits(GPIOA, GPIO_Pin_6);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == 0){
key_line = 4;
GPIO_SetBits(GPIOA, GPIO_Pin_7);
}
else key_line = 0;
switch(key_line)
{
case 1:key_val = '4';break;
case 2:key_val = '5';break;
case 3:key_val = '6';break;
case 4:key_val = 'B';break;
}
key_line = 0;
keypads_linescan_IPU();
keypads_rowscan_Out_PP();
}
else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2) == 0){
keypads_linescan_Out_PP();
keypads_rowscan_IPU();
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 0){
key_line = 1;
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0){
key_line = 2;
GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6) == 0){
key_line = 3;
GPIO_SetBits(GPIOA, GPIO_Pin_6);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == 0){
key_line = 4;
GPIO_SetBits(GPIOA, GPIO_Pin_7);
}
else key_line = 0;
switch(key_line)
{
case 1:key_val = '7';break;
case 2:key_val = '8';break;
case 3:key_val = '9';break;
case 4:key_val = 'C';break;
}
key_line = 0;
keypads_linescan_IPU();
keypads_rowscan_Out_PP();
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8) == 0){
keypads_linescan_Out_PP();
keypads_rowscan_IPU();
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 0){
key_line = 1;
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0){
key_line = 2;
GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6) == 0){
key_line = 3;
GPIO_SetBits(GPIOA, GPIO_Pin_6);
}
else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == 0){
key_line = 4;
GPIO_SetBits(GPIOA, GPIO_Pin_7);
}
else key_line = 0;
switch(key_line)
{
case 1:key_val = '*';break;
case 2:key_val = '0';break;
case 3:key_val = '#';break;
case 4:key_val = 'D';break;
}
key_line = 0;
keypads_linescan_IPU();
keypads_rowscan_Out_PP();
}
return key_val;
}
之后就是键盘扫描程序,在检测到行电平之后进入switch,然后将行IO口切换为推挽输出,列IO口切换为上拉输入,这样是最简单但是是最直观的写法。
之前写的键盘扫描没有在检测的时候加入IO口类型切换,虽然测试的时候很正常,但是换了其他的条件之后(比如换了电源,换了其他电路板等情况),就变得不正常,按键在特定情况下才有输出(原因一直还没有排查清楚)。
总之,最妥善的写法还是需要加上IO口状态的切换。