注意:IO口都要上拉。
一、IO口设置为开漏输出:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
二、扫描程序:
uint8_t KeyScan(void)
{
int tmp;
static int KeyConter = 0;
int keyval;
keyval = 0xFF;
if (KeyConter < 1)
{//去抖
KeyConter++;
}
else
{
keyval = 0xFF;
GPIO_Write(GPIOA, 0x0F); //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
keyval &= tmp;
GPIO_Write(GPIOA, 0xF0);//列
选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0x0F);//
读取此时的行选的值
keyval &= tmp; //两次的结果相与得到是一个唯一值,既一个按键按下只有一个keyval与之对应
switch (keyval)
{
case 0xee: return 1;
case 0xde: return 2;
case 0xbe: return 3;
case 0x7e: return 4;
case 0xed: return 5;
case 0xdd: return 6;
case 0xbd: return 7;
case 0x7d: return 8;
case 0xeb: return 9;
case 0xdb: return 10; //*
case 0xbb: return 11;
case 0x7b: return 12; //#
case 0x77: return 13; //下一位
default: return 0;
}
KeyConter=0;
}
}
------------------------
你的IO口多的用不掉的话可以。。
首先是GPIO_Write(GPIOA, 0x0F); //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
上面的语句如果只读列的话,为什么不用&而是|。还有一个问题是当开关按下的时候,两端是低电平的时候导通,为什么不是高电平,开关两端的上拉对这个电平没有影响吗
请教一下,单片机引脚应该是读取电阻右边的电平吧?
GPIO_Write(GPIOA, 0x0F); //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
PA0~PA3置1,假设S1按下,那么PA4读取的状态是跟PA0相同是1吧?PA5~PA7(S2~S4)右侧没信号,但是左侧上拉应该读取都是1吧。
不是很明白,求解惑
我自己的理解是这样的,当拉高后是高电平,两边都是1;但是在按键按下的时候由于两边电平一样就会变成0,所以在开关按下的时候应该是低电平。还有tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值;这句我感觉是不是应该读取行的值
一周热门 更多>