矩阵按键
1.主要内容(扫描原理):
方法一:
逐行扫描:通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
方法二:
行列扫描:通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
2.编写程序:
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
#define GPIO_KEY P1 //定义矩阵键盘接口
#define GPIO_DIG P0 //发送断码端口
u8 keyvalue;
u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay(u16 i)
{
while(i--);
}
void KeyDown() //实现行列扫描
{
u8 a;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f) //判断是否按下
{
delay(1000);
if(GPIO_KEY!=0x0f)
{
GPIO_KEY=0x0f;
switch(GPIO_KEY)
{
case(0x07):keyvalue=0;break;
case(0x0b):keyvalue=1;break;
case(0x0d):keyvalue=2;break;
case(0x0e):keyvalue=3;break;
}
GPIO_KEY=0xf0;
switch(GPIO_KEY)
{
case(0x70):keyvalue=keyvalue;break;
case(0xb0):keyvalue=keyvalue+4;break;
case(0xd0):keyvalue=keyvalue+8;break;
case(0xe0):keyvalue=keyvalue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0))
{
delay(1000);
a++;
}
}
}
}
void main()
{
LSA=0;
LSB=0;
LSC=0;
while(1);
{
KeyDown();
GPIO_DIG=smgduan[keyvalue];
}
}
8×8点阵
1.主要内容:
注:P0控制第七列,D0控制第八行。
原理:显示汉字与数字:通过LED拼接数字图形,采用动态扫描的方式,发送断选数据,循环点亮每一列,点亮一列,发送一列数据。
2.编写程序:
a.点亮左上角第一个:
#include<reg51.h>
#include<intrins.h> //定义左移右移,调用该头文件
typedef unsigned char u8;
typedef unsigned int u16;
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^6;
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK=0;
RCLK=0;
for(a=0;a<8;a++)
{
SER=dat>>7; //595芯片SER最先传送最高位,移七次位
dat<<=1; //左移一位传送次高位eg.1001 1001右移七次后变为1,左移一位后变为0011 0010
SRCLK=1;
_nop_(); //延时
_nop_();
SRCLK=0; //让电平拉低,循环形成高电平,由高低循环形成上升沿
}
RCLK=1;
_nop_();
_nop_();
RCLK=0; //原理同上
}
void main()
{
Hc595SendByte(0x80); //D7s输出高电平,其余为低电平
P0=0x7f; //0111 1111
while(1);
}
b.点亮0:
#include<reg51.h>
#include<intrins.h> //定义左移右移,调用该头文件
typedef unsigned char u8;
typedef unsigned int u16;
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^6;
u8 ledduan[]={0x00,0x00,0x41,0x41,0x41,0x3e}; //列
u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //保存每一列的数据//定义数组进行扫描
void delay(u16 i) //采用动态扫描,有延时函数
{
while(i--);
}
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK=0;
RCLK=0;
for(a=0;a<8;a++)
{
SER=dat>>7; //595芯片SER最先传送最高位,移七次位
dat<<=1; //左移一位传送次高位eg.1001 1001右移七次后变为1,左移一位后变为0011 0010
SRCLK=1;
_nop_(); //延时
_nop_();
SRCLK=0; //让电平拉低,循环形成高电平,由高低循环形成上升沿
}
RCLK=1;
_nop_();
_nop_();
RCLK=0; //原理同上
}
void main()
{
u8 i;
while(1) //动态显示,用for循环实现发送八个字节
{
P0=0x7f; //第一列选通(最高位为零),再进行循环
for(i=0;i<8;i++)
{
P0=ledwei[i]; //控制wei
Hc595SendByte(ledduan[i]); //发送数据,调用ledduan[i]
delay(100);
Hc595SendByte(0x00); //断选数据不显示(清零),进行消隐
}
}
}