OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8672|回复: 9

求解释。矩阵键盘输入实验。

[复制链接]

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
发表于 2013-7-12 20:26:39 | 显示全部楼层 |阅读模式
GPIOE->CRH&=0X00000000;
GPIOE->CRH|=0X33333333;
GPIOE->ODR|=0xff00;

GPIOE->CRH&=0x00000000; 
GPIOE->CRH|=0X44444444; 

GPIOE->CRH&=0XFFFFFFF0;
GPIOE->CRH|=0X00000003; 
各种不懂,第一段的第三行是什么意思?为什么第一段已经设置为PE推挽输出,第二段还要设置浮空输入,第三段又将PE8设置成推挽输出? 

不求甚解
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2013-7-12 20:34:41 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
 楼主| 发表于 2013-7-12 20:47:31 | 显示全部楼层


不求甚解
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2013-7-12 21:08:03 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
 楼主| 发表于 2013-7-12 21:49:43 | 显示全部楼层
回复【4楼】xouou_53320:
---------------------------------
差不多吧,这是stm32的键盘输入实验。。。
代码太长了。。。

#include <stm32f10x_lib.h>
#include "key.h"
#include "delay.h"   
    
//按键初始化函数
void Matrix_Keyboard_Init(void)
{
RCC->APB2ENR|=1<<6;     //使能PORTE时钟
GPIOE->CRH&=0X00000000;//将PE设置成out——pp输出 
GPIOE->CRH|=0X33333333;


u8 key;
u8 Matrix_Keyboard_Scan(void)
{  
//char i;
u16 temp; 

GPIOE->CRH&=0X00000000;//将PE设置成out——pp输出  
GPIOE->CRH|=0X33333333;
GPIOE->ODR|=0xff00;

GPIOE->CRH&=0x00000000; /////去除将PEx设置成out——pp输出是的某些设置位 
GPIOE->CRH|=0X44444444; /////配置为浮空输入了

GPIOE->CRH&=0XFFFFFFF0;//将PE8设置成out——pp输出 
GPIOE->CRH|=0X00000003; 

PE8=0;

temp=GPIOE->IDR;
temp&=0xFF00;
if(temp!=0xFE00)
{
switch(temp)
{
case 0xee00: key=2;break;
case 0xde00: key=3;break;
case 0xbe00: key=4;break;
case 0x7e00: key=5;break;

temp=GPIOE->IDR;
temp&=0xf000;
while(temp!=0xf000)//知道按键松开
{
temp=GPIOE->IDR;
temp&=0xf000;


GPIOE->CRH&=0X00000000;//将PE设置成out——pp输出 
GPIOE->CRH|=0X33333333;
//for(i=15;i>=8;i--)  
GPIOE->ODR|=0xff00; 
GPIOE->CRH&=0x00000000;
GPIOE->CRH|=0X44444444;
GPIOE->CRH&=0XFFFFFF0F; //PE9设置成out——pp输出 
GPIOE->CRH|=0X00000030;
PE9=0;
temp=GPIOE->IDR;
temp&=0xff00;
if(temp!=0xfd00)

switch(temp)
{
case 0xed00: key=6;break;
case 0xdd00: key=7;break;
case 0xbd00: key=8;break;
case 0x7d00: key=9;break;

temp=GPIOE->IDR;
temp&=0xf000;
while(temp!=0xf000)
{
temp=GPIOE->IDR;
temp&=0xf000;



GPIOE->CRH&=0X00000000;//将PE设置成out——pp输出 
GPIOE->CRH|=0X33333333;
//for(i=15;i>=8;i--)  
GPIOE->ODR|=0xff00;
GPIOE->CRH&=0x00000000; 
GPIOE->CRH|=0X44444444; 
GPIOE->CRH&=0XFFFFF0FF;//PE10设置成out——pp输出 
GPIOE->CRH|=0X00000300; 
PE10=0; 

temp=GPIOE->IDR;
temp&=0xff00;
if(temp!=0xfb00)
{

switch(temp)
{
case 0xeb00: key=10;break;
case 0xdb00: key=11;break;
case 0xbb00: key=12;break;
case 0x7b00: key=13;break;

temp=GPIOE->IDR;
temp&=0xf000;
while(temp!=0xf000)
{
temp=GPIOE->IDR;
temp&=0xf000;




GPIOE->CRH&=0X00000000; 
GPIOE->CRH|=0X33333333;  
//for(i=15;i>=8;i--)  
GPIOE->ODR|=0xff00;
GPIOE->CRH&=0x00000000; 
GPIOE->CRH|=0X44444444; 
GPIOE->CRH|=0X00003000;//将PE11设置成out——pp输出 
PE11=0;
temp=GPIOE->IDR;
temp&=0xff00;
if(temp!=0xf700)
{
switch(temp)
{
case 0xe700: key=14;break;
case 0xd700: key=15;break;
case 0xb700: key=16;break;
case 0x7700: key=1;break;

temp=GPIOE->IDR;
temp&=0xf000;
while(temp!=0xf000)
{
temp=GPIOE->IDR;
temp&=0xf000;


return key; 
}

u8 Key_Down(void)
{
// char i = 0;
u16 temp;
GPIOE->CRH&=0X00000000; 
GPIOE->CRH|=0X33333333;
GPIOE->ODR|=0Xff00;
 
GPIOE->CRH&=0x00000000;
GPIOE->CRH|=0X44444444;

delay_ms(20) ;
temp=GPIOE->IDR;
// temp&=0xff00;
if(temp!=0xff00)
return 1;
else return 0;
不求甚解
回复 支持 反对

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
 楼主| 发表于 2013-7-12 21:52:46 | 显示全部楼层
回复【4楼】xouou_53320:
---------------------------------
还有,if(temp!=0xFE00)这个怎么理解?
不求甚解
回复 支持 反对

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
 楼主| 发表于 2013-7-12 22:07:38 | 显示全部楼层
回复【4楼】xouou_53320:
---------------------------------
还有,GPIOE->ODR|=0xff00;这个??
不求甚解
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2013-7-13 08:39:59 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

11

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2013-7-10
在线时间
0 小时
 楼主| 发表于 2013-7-13 09:29:14 | 显示全部楼层
回复【8楼】xouou_53320:
---------------------------
灰常感谢!!
不求甚解
回复 支持 反对

使用道具 举报

50

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
492
金钱
492
注册时间
2013-2-2
在线时间
0 小时
发表于 2013-8-14 10:38:54 | 显示全部楼层
回复【8楼】xouou_53320:
---------------------------------
我写的键盘程序,不知道为什么键盘要按好几次才有反应,而且有时候不知道为什么,两次按下去显示的键值是不一样的,能帮我看看错在哪了吗?

void InitKeyBoard(void) //初始化矩阵键盘要使用的GPIO口。
{
GPIO_InitTypeDef  GPIOStru;

GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP;  //定义PA0到PA3为推挽输出。
    GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
    GPIOStru.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_Init(GPIOA,&GPIOStru);

GPIOStru.GPIO_Mode = GPIO_Mode_IPD;  //定义PA4到PA7为下拉输入。
    GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
    GPIOStru.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;

//因为上面定义引脚为输出时,已经打开整个GPIOA的时钟了,所以此处不再需要函数RCC_APB2PeriphClockCmd()来打开时钟了。
    GPIO_Init(GPIOA,&GPIOStru);
}

int keyBoard(void)  //实现矩阵键盘。返回值为,各按键的键值,此键值由用户自己定义。
{
int KeyVal=0;  //keyVal为最后返回的键值。

GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0xf)); //先让PA0到PA3全部输出高。

if((GPIOA->IDR & 0x00f0)==0x0000)  //如果,PA4到PA7全为0,则,没有键按下。此时,返回值为-1.
return -1;
else
{
Delay(10000);    //延时5ms去抖动。
if((GPIOA->IDR & 0x00f0)==0x0000)  //如果,延时5ms后,PA4到PA7又全为0,则,刚才引脚的电位变化是抖动产生的.
return -1;
}

GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0x1)); //让PA3到PA0输出二进制的0001.
switch(GPIOA->IDR & 0x00f0)                 //对PA4到PA7的值进行判断,以输出不同的键值。
{
case 0x0010:
{
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0010)
{
while((GPIOA->IDR & 0x00f0)==0x0010);
KeyVal=1;
}

}break;
case 0x0020: 
{
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0020)
{
while((GPIOA->IDR & 0x00f0)==0x0020);
KeyVal=2;
}
}break;
case 0x0040: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0040)
{
while((GPIOA->IDR & 0x00f0)==0x0040);
KeyVal=3;
}
 }break;
case 0x0080: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0080)
{
while((GPIOA->IDR & 0x00f0)==0x0080);
KeyVal=4;
}
 }break;
}

GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0x2)); //让PA3到PA0输出二进制的0010.
switch(GPIOA->IDR & 0x00f0)                 //对PA4到PA7的值进行判断,以输出不同的键值。
{
case 0x0010: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0010)
{
while((GPIOA->IDR & 0x00f0)==0x0010);
KeyVal=5;
}
 }break;
case 0x0020: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0020)
{
while((GPIOA->IDR & 0x00f0)==0x0020);
KeyVal=6;
}
 }break;
case 0x0040: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0040)
{
while((GPIOA->IDR & 0x00f0)==0x0040);
KeyVal=7;
}
 }break;
case 0x0080: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0080)
{
while((GPIOA->IDR & 0x00f0)==0x0080);
KeyVal=8;
}
 }break;
}

GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0x4)); //让PA3到PA0输出二进制的0100.
switch(GPIOA->IDR & 0x00f0)                 //对PA4到PA7的值进行判断,以输出不同的键值。
{
case 0x0010: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0010)
{
while((GPIOA->IDR & 0x00f0)==0x0010);
KeyVal=9;
}
 }break;
case 0x0020: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0020)
{
while((GPIOA->IDR & 0x00f0)==0x0020);
KeyVal=10;
}
 }break;
case 0x0040: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0040)
{
while((GPIOA->IDR & 0x00f0)==0x0040);
KeyVal=11;
}
 }break;
case 0x0080: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0080)
{
while((GPIOA->IDR & 0x00f0)==0x0080);
KeyVal=12;
}
 } break;
}

GPIO_Write(GPIOA,(GPIOA->ODR & 0xfff0 | 0x8)); //让PA3到PA0输出二进制的1000.  
switch(GPIOA->IDR & 0x00f0)                 //对PA4到PA7的值进行判断,以输出不同的键值。
{
case 0x0010: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0010)
{
while((GPIOA->IDR & 0x00f0)==0x0010);
KeyVal=13;
}
 }break;
case 0x0020: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0020)
{
while((GPIOA->IDR & 0x00f0)==0x0020);
KeyVal=14;
}
 }break;
case 0x0040: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0040)
{
while((GPIOA->IDR & 0x00f0)==0x0040);
KeyVal=15;
}
 }break;
case 0x0080: {
Delay(10000); 
if((GPIOA->IDR & 0x00f0)==0x0080)
{
while((GPIOA->IDR & 0x00f0)==0x0080);
KeyVal=16;
}
 }break;
}

return KeyVal;
}


int main(void)
 {
    u8 Number;
InitKeyBoard();
SystemInit();
delay_init(72);      //延时初始化
NVIC_Configuration();
LCD5110_GPIOInit();
LCD5110Clear();                
while(1) 
{
Number=keyBoard();  
switch(Number)
{
case 1: delay_ms(10);LCD5110WriteEnStr(0,2,"A");delay_ms(10);break;
case 2: delay_ms(10);LCD5110WriteEnStr(0,2,"B");delay_ms(10);break;
case 3: delay_ms(10);LCD5110WriteEnStr(0,2,"C");delay_ms(10);break;
case 4: delay_ms(10);LCD5110WriteEnStr(0,2,"D");delay_ms(10);break;
case 5: delay_ms(10);LCD5110WriteEnStr(0,2,"E");delay_ms(10);break;
case 6: delay_ms(10);LCD5110WriteEnStr(0,2,"F");delay_ms(10);break;
case 7: delay_ms(10);LCD5110WriteEnStr(0,2,"G");delay_ms(10);break;
case 8: delay_ms(10);LCD5110WriteEnStr(0,2,"H");delay_ms(10);break;
case 9: delay_ms(10);LCD5110WriteEnStr(0,2,"I");delay_ms(10);break;  
case 10: delay_ms(10);LCD5110WriteEnStr(0,2,"J");delay_ms(10);break;
case 11: delay_ms(10);LCD5110WriteEnStr(0,2,"K");delay_ms(10);break;
case 12: delay_ms(10);LCD5110WriteEnStr(0,2,"L");delay_ms(10);break;
case 13: delay_ms(10);LCD5110WriteEnStr(0,2,"M");delay_ms(10);break;
case 14: delay_ms(10);LCD5110WriteEnStr(0,2,"N");delay_ms(10);break;
case 15: delay_ms(10);LCD5110WriteEnStr(0,2,"O");delay_ms(10);break;
}
}

 }
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-15 02:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表