按键能在第1位数码管上显示,但不能移位显示,还望高手们帮忙看看。
现在遇到的问题是按键只在第一位显示,按什么显什么,但是不会到下一位显示,这不是我想要的,我想把按键都存到dispbuf[ i ]这个数组里面,然后把数组里面的数字显示出来。
“i++;”移位加在什么地方都没用。
附件里包括了proteus 跟 C
#include<reg51.h>
#include<absacc.h>
#include <string.h>
#include <intrins.h>
#define COM8155 XBYTE[0xff20] //8155控制口地址
#define PA XBYTE[0xff21] //8155A口地址
#define PB XBYTE[0xff22] //8155B口地址
#define uchar unsigned char
#define uint unsigned int
#define SCANPORT P1
sbit P33=P3^3;
sbit P34=P3^4;
sbit P35=P3^5;
unsigned code seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示段位
unsigned dispbuf[8]={0}; //显示缓存
unsigned dispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数位扫描
unsigned char uca_LineScan[4]={0xEF,0xDF,0xBF,0x7F}; //列线扫描电压,分为第1,2,3,4根列线
unsigned code pwd[8]={0};
uint key_code;
uchar i; //第几次按键
unsigned char key;
void change_pwd();
void check_pwd();
uchar keyscan();
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<防抖动标志>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
bit b_KeyShock=0; //键盘防抖动标志位。
//当按键中断产生时,首先判断此位。
//0--执行键盘扫描及键码处理程序;1--不执行。
bit b_KillShock=0; //防抖标志清除位:0--不清除;1--清除。
/**************************************************************************************/
void delay(uint i)
{
while(--i);
}
/**************************************************************************************/
/**************************************************************************************/
unsigned char keyscan(void)
{
unsigned char ucTemp=0; //扫描状态暂存。
unsigned char ucRow=0,ucLine=0; //行号,列号。
for(ucLine=0;ucLine<4;ucLine++) //列扫描
{
SCANPORT=uca_LineScan[ucLine]; //输出扫描电位。
ucTemp=SCANPORT&0x0F; //输入扫描电位,并屏蔽高4位。
if(ucTemp!=0x0F)
{ //判断该列是否有按键按下。
switch(ucTemp)
{
case 0x0E: ucRow=10;break; //如果有,则判断行号。
case 0x0D: ucRow=20;break;
case 0x0B: ucRow=30;break;
case 0x07: ucRow=40;break;
default: ucRow=50;break;
}
break;
}
}
return ucRow+ucLine+1; //返回按键编码。格式为2位数,高位为行号,低位为列号。
}
/***************************************************************************************/
/**************************************************************************************/
uint getkey(uint keycode)
{
switch(keycode)
{
case 11:key=7;break;
case 12:key=8;break;
case 13:key=9;break;
case 21:key=4;break;
case 22:key=5;break;
case 23:key=6;break;
case 31:key=1;break;
case 32:key=2;break;
case 33:key=3;break;
/* case 41:change_pwd();break; */
case 42:key=0;break;
/* case 43:check_pwd();break; */
default: break;
}
return(key);
}
/****************************************************************************************/
//*************************************************************************************************
//* *
//* ***************************外部中断0,调用键盘扫描程序************************* *
//* *
//*************************************************************************************************
void vINT0(void) interrupt 0
{
EX0=0; //在键扫描处理时,关闭外部中断0,防抖动。
if(b_KeyShock==0)
{
//当判断有按键按下时,扫描键盘,并把扫描结果进行处理。
key_code=keyscan(); //把按键存放
b_KeyShock=1; //设置防抖动标志。
}
else b_KeyShock=0; //如果有抖动则不执行键扫描,恢复防抖动标志。
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<设置防抖动清除标志位 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(b_KeyShock==1)
b_KillShock=1; //如果防抖动标志位开启则开启防抖动标志清除位,
//300ms后清除防抖动标志。
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<恢复键扫描处理前初始状态 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SCANPORT=0x0F; //恢复P2口。
EX0=1; //恢复按键中断。
i++;
}
/***************************************************************************************/
void display()
{
uchar p;
for(p=0;p<8;p++)
{switch(p)
{case 0:{P33=0
34=0
35=0;}break;case 1:{P33=1
34=0
35=0;}break;case 2:{P33=0
34=1
35=0;}break;case 3:{P33=1
34=1
35=0;}break;case 4:{P33=0
34=0
35=1;}break;case 5:{P33=1
34=0
35=1;}break;case 6:{P33=0
34=1
35=1;}break;case 7:{P33=1
34=1
35=1;}break;default : break;
}
P2=seg[dispbuf[p]];
delay(20);
}
}
/***************************************************************************************/
void main()
{
SCANPORT=0x0F; //初始化键盘接口。
EA=1;
EX0=1;
IT0=0;
while(1)
{
dispbuf=getkey(key_code);
display();
}
}
[ 本帖最后由 leolle 于 2008-7-24 10:15 编辑 ]
password2.rar
(2008-07-24 09:05:27, Size: 125 KB, Downloads: 17)

最新回复
vincent_tsai (2008-7-24 09:13:27)
panhearii (2008-7-24 09:21:01)
楼主的中断函数太长了 按键的时候 DISPLAY得不到执行 是不是指这个??
leolle (2008-7-24 10:09:39)
上次你们说我中断里面太复杂了,现在已经改过了,中断里面只调用了一道子函数,就是把键盘的行列码扫出来送给key_code,然后再在主程序里面去判断它真正的键值。
现在遇到的问题是按键只在第一位显示,按什么显什么,但是不会到下一位显示,这不是我想要的,我想把按键都存到dispfuf这个数组里面,然后把数组里面的数字显示出来。
[ 本帖最后由 leolle 于 2008-7-24 10:11 编辑 ]
panhearii (2008-7-24 10:51:01)
b_KillShock=1; //如果防抖动标志位开启则开启防抖动标志清除位,
//300ms后清除防抖动标志。
这都没改 300MS清抖动在哪呢???
51是8位单片机 变量已CHAR为主 INT的处理时间要高出不少
凌阳是16位的 也不宜用8位的变量
是LOCK A那张图吧?
你的附件中
uchar i 从始至终都没变过 一直为0 所以被改变的自然也就只有第0位了
你上面贴的程序里又出现了i++。。。。。。搞得都没耐心了
楼主请更新附件
正在继续看
leolle (2008-7-24 11:07:25)
另外我问我们实验室一高手他说其实去抖可有可无的。
再加上我自己把那几行删了也没什么关系。
[ 本帖最后由 leolle 于 2008-7-24 11:09 编辑 ]
panhearii (2008-7-24 11:13:10)
#include<absacc.h>
#include <string.h>
#include <intrins.h>
#define COM8155 XBYTE[0xff20] //8155控制口地址
#define PA XBYTE[0xff21] //8155A口地址
#define PB XBYTE[0xff22] //8155B口地址
#define uchar unsigned char
#define uint unsigned int
#define SCANPORT P1
sbit P33=P3^3;
sbit P34=P3^4;
sbit P35=P3^5;
unsigned code seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示段位
unsigned dispbuf[8]={0}; //显示缓存
unsigned dispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数位扫描
unsigned char uca_LineScan[4]={0xEF,0xDF,0xBF,0x7F}; //列线扫描电压,分为第1,2,3,4根列线
unsigned code pwd[8]={0};
uint key_code;
uchar i; //第几次按键
unsigned char key;
void change_pwd();
void check_pwd();
uchar keyscan();
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<防抖动标志>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
bit b_KeyShock=0; //键盘防抖动标志位。
//当按键中断产生时,首先判断此位。
//0--执行键盘扫描及键码处理程序;1--不执行。
bit b_KillShock=0; //防抖标志清除位:0--不清除;1--清除。
/**************************************************************************************/
void delay(uint i)
{
while(--i);
}
/**************************************************************************************/
/**************************************************************************************/
unsigned char keyscan(void)
{
unsigned char ucTemp=0; //扫描状态暂存。
unsigned char ucRow=0,ucLine=0; //行号,列号。
for(ucLine=0;ucLine<4;ucLine++) //列扫描
{
SCANPORT=uca_LineScan[ucLine]; //输出扫描电位。
ucTemp=SCANPORT&0x0F; //输入扫描电位,并屏蔽高4位。
if(ucTemp!=0x0F)
{ //判断该列是否有按键按下。
switch(ucTemp)
{
case 0x0E: ucRow=10;break; //如果有,则判断行号。
case 0x0D: ucRow=20;break;
case 0x0B: ucRow=30;break;
case 0x07: ucRow=40;break;
default: ucRow=50;break;
}
break;
}
}
return ucRow+ucLine+1; //返回按键编码。格式为2位数,高位为行号,低位为列号。
}
/***************************************************************************************/
/**************************************************************************************/
uint getkey(uint keycode)
{
switch(keycode)
{
case 11:key=7;break;
case 12:key=8;break;
case 13:key=9;break;
case 21:key=4;break;
case 22:key=5;break;
case 23:key=6;break;
case 31:key=1;break;
case 32:key=2;break;
case 33:key=3;break;
/* case 41:change_pwd();break; */
case 42:key=0;break;
/* case 43:check_pwd();break; */
default: break;
}
return(key);
}
/****************************************************************************************/
//*************************************************************************************************
//* *
//* ***************************外部中断0,调用键盘扫描程序************************* *
//* *
//*************************************************************************************************
void vINT0(void) interrupt 0
{
EX0=0; //在键扫描处理时,关闭外部中断0,防抖动。
if(b_KeyShock==0)
{
//当判断有按键按下时,扫描键盘,并把扫描结果进行处理。
key_code=keyscan(); //把按键存放
i++;if(i==8){i=0;}
b_KeyShock=1; //设置防抖动标志。
}
else b_KeyShock=0; //如果有抖动则不执行键扫描,恢复防抖动标志。
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<设置防抖动清除标志位 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/*if(b_KeyShock==1)
b_KillShock=1; //如果防抖动标志位开启则开启防抖动标志清除位,
*/ //300ms后清除防抖动标志。
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<恢复键扫描处理前初始状态 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SCANPORT=0x0F; //恢复P2口。
EX0=1; //恢复按键中断。
}
/***************************************************************************************/
void display()
{
uchar p;
for(p=0;p<8;p++)
{switch(p)
{case 0:{P33=0
case 1:{P33=1
case 2:{P33=0
case 3:{P33=1
case 4:{P33=0
case 5:{P33=1
case 6:{P33=0
case 7:{P33=1
default : break;
}
P2=seg[dispbuf[p]];
delay(20);
}
}
/***************************************************************************************/
void main()
{
SCANPORT=0x0F; //初始化键盘接口。
EA=1;
EX0=1;
IT0=0;
while(1)
{
dispbuf=getkey(key_code);
display();//
}
}
这样就行了 你的键盘扫描还是有点问题 自己试了就知道
panhearii (2008-7-24 11:16:11)
这个仁者见仁 智者见智
楼主看看你的程序 去抖没去好的 很惨~~~~
那几行删不删都不影响程序运行 但是直接影响别人对你的看法
你说我是觉得你懒呢 还是不懂呢 还是什么呢?
我说话难听 请别见怪。。。。。。。。。。。。
另:本人最近辞工回学校读书 为不增加父母负担 且保一日三餐 提供各种有偿服务
邮箱 www.panheariii@hotmail.com
[ 本帖最后由 panhearii 于 2008-7-24 11:19 编辑 ]
leolle (2008-7-24 11:24:38)
现在虽然能移位,但好像按一次键能输入几次数,时序出了很大的问题。
leolle (2008-7-24 11:28:47)
leolle (2008-7-24 11:30:22)
panhearii (2008-7-24 11:31:33)
300MS的延迟
你补上试试
由于我现在已经替换成STC的片子了 所以现在的按键全是用AD做的
一个口接64个键 我是当3次扫描的键值都一致时 确认键值 然后3次扫描都为按键释放时 执行上一次的键值
即松开按键才进行处理 没有标准的按键延迟去抖(不过我AD那做了软件滤波。。。还有一片104)
另:本人最近辞工回学校读书 为不增加父母负担 且保一日三餐 提供各种有偿服务
邮箱 www.panheariii@hotmail.com
leolle (2008-7-24 11:36:38)
上面加了按键释放以后你们说while那个地方是致命的问题。
panhearii (2008-7-24 11:43:45)
这样做 领导是不会给你好脸色看的
void delay(uint i)
{
while(i){i--;}
}
这样写 大家不至于鄙视你
我再翻翻上次那程序
leolle (2008-7-24 15:03:35)
绝处逢生 (2008-7-24 15:36:24)
绝处逢生 (2008-7-24 15:41:56)
panhearii (2008-7-24 15:55:04)
case 1:{P33=134=0
复制过去时 笑脸被忽略了
i值在取得键值后立即++
键值能取 i就能变
key_code=keyscan(); //把按键存放
i++;if(i==8){i=0;}
[ 本帖最后由 panhearii 于 2008-7-24 15:56 编辑 ]
leolle (2008-7-24 15:57:15)
delay(50);
if(INT0==1)
return;
好像不行啊。扫出来的还是乱序的。
panhearii (2008-7-24 15:58:28)
QUOTE:
能正确显示 就是防抖动没做 i值乱加leolle (2008-7-24 16:06:04)