74HC 164键盘扫描程序问题
#include "REG52.H"
#include "stdio.h"
#include "intrins.h"
?
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^4;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^6;
sbit LCD_BG=P2^3; //当LCD_BG=0时LCD1602屏幕不亮,当LCD_BG=1时LCD1602屏幕亮
uchar code table[]="0123456789 ";
void LCD_init();
void display_xy(uchar x,uchar y);
void display_int(uchar x,uchar y,int num);
sbit key_clk=P3^4;
sbit key_dat=P3^5;
sbit key_row1=P3^6;
sbit key_row2=P3^7;
uchar row,key=0;
uchar buffer;
void key_sendbyte(uchar byte);
uchar key_value();
void key_scan();
void Delayms(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=135;j>0;j--);
}
/*****LCD1602初始化********/
void Busy()
{
uchar temp=0x80; //初始化temp最高位为1,使得能够进入下面的while循环
P0=0xff; //(P0就是8个数据口)
LCD_RS=0; //设置命令操作
LCD_RW=1; //设置读操作
LCD_EN=1; //使能
Delayms(5); //(这是设的延时函数,不用解释)
while(temp & 0x80) //判忙,一旦表达式为假,即temp最高位为0,则表示1602不忙,跳出while.
{
temp=P0;
Delayms(10); //把p0的的高位读入temp,延时
}
LCD_EN=0; //关闭使能信号
}
/*写指令数据到LCD */
void LCD_wcmd(uchar cmd)
{
Busy(); //忙闲信号的判断
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
P0 = cmd;
Delayms(5);
LCD_EN = 1;
Delayms(5);
LCD_EN = 0;
}
/*写显示数据到LCD */
void LCD_wdat(uchar dat)
{
Busy();
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
Delayms(5);
LCD_EN = 1;
Delayms(10);
LCD_EN = 0;
}
/*LCD初始化*/
void LCD_init()
{
LCD_wcmd(0x38); //16*2显示,5*7点阵,8位数据
Delayms(5);
LCD_wcmd(0x38); //16*2显示,5*7点阵,8位数据
Delayms(5);
LCD_wcmd(0x38);
Delayms(5); //三次初始化,确保完成
LCD_wcmd(0x0c); //显示开,关光标
Delayms(5);
LCD_wcmd(0x06); //移动光标
Delayms(5);
LCD_wcmd(0x01); //清除LCD的显示内容
Delayms(5);
}
/*设置光标位置, x是列号,y是行号*/
void display_xy(uchar x,uchar y)
{
// LCD_wcmd(0x01); //清楚光屏
if(y==1)
x+=0xc0; //0xc0第二行首地址
else
x+=0x80; //0x80第一行首地址
LCD_wcmd(x);
}
/*在具体位置显示一个整数*/
void display_int(uchar x,uchar y,long num)
{
uint a,b,c,d,e;
a=num/10000; // 万位
b=num%10000/1000; // 千位
c=num%10000%1000/100; // 百位
d=num%10000%1000%100/10; // 十位
e=num%10; // 个位
display_xy(x,y);
if(num<0)
{
LCD_wdat(0xb0);
a=-a;
b=-b;
c=-c;
d=-d;
e=-e;
}
if(a!=0)
LCD_wdat(table[a]);
if(a!=0|b!=0)
LCD_wdat(table);
if(a!=0|b!=0|c!=0)
LCD_wdat(table[c]);
if(a!=0|b!=0|c!=0|d!=0)
LCD_wdat(table[d]);
LCD_wdat(table[e]);
}
//2*8键盘
void key_sendbyte(uchar byte) //串行输出子程序
{
uint i; //局部变量i
for(i=0;i<8;i++) //循环8次
{
key_clk=0; //将时钟信号设为低电平
key_dat=byte&0x80; //(0x80即十进制的128, 二进制的10000000 按位发送)
key_clk=1; //再将时钟信号设置为高电平,将输出一个时钟信号的上升沿
byte<<= 1; //byte变量左移一位
}
}
uchar key_value()
{
uchar key_bit,i;
buffer=0xff;
key_sendbyte(0x00);
if(!(key_row1&key_row2))
{
Delayms(10); //消除按键抖动
if(!(key_row1&key_row2)) //有键按下
{
if(!key_row1) //第一行有键按下
{
row=0;
key_bit=0xfe;
for(i=0;i<8;i++)
{
key_sendbyte(key_bit); //查看是否是这个数值的键按下
if(!key_row1)
{
buffer=key_bit; //如果是,把键值存入buffer
break;
}
key_bit = _crol_(key_bit,1); //如果不是,进行是否是下一个键按下的断定
}
return buffer; //返回键值
}
if(!key_row2) //第二行有键按下
{
row=1;
key_bit=0xfe;
for(i=0;i<8;i++)
{
key_sendbyte(key_bit); //查看是否是这个数值的键按下
if(!key_row2)
{
buffer=key_bit; //如果是,把键值存入buffer
break;
}
key_bit = _crol_(key_bit,1); //如果不是,进行是否是下一个键按下的断定
}
return buffer; //返回键值
}
}
}
}
void key_scan()
{
uchar temp=0;
temp=key_value();
if(row==0)
{
switch(temp)
{
case 0xfe:key=1;break;
case 0xfd:key=2;break;
case 0xfb:key=3;break;
case 0xf7:key=4;break;
case 0xef:key=5;break;
case 0xdf:key=6;break;
case 0xbf:key=7;break;
case 0x7f:key=8;break;
default:break;
}
}
else
{
switch(temp)
{
case 0xfe:key=9;break;
case 0xfd:key=10;break;
case 0xfb:key=11;break;
case 0xf7:key=12;break;
case 0xef:key=13;break;
case 0xdf:key=14;break;
case 0xbf:key=15;break;
case 0x7f:key=16;break;
default:break;
}
}
}
void main ()
{
LCD_init(); // 初始化LCD
LCD_BG=1;
while(1)
{
key_scan();
display_int(0,0,key);
display_int(0,1,buffer);
}
}
程序扫描不大键盘,不知为什么?