书上原来是汇编程序,我给修改了用PORTD输出扫描到的按键码,可以正常的显示,按下某个按键,就会显示出某个按键码,延时结束后,LED就会灭掉。而修改成C程序,按下某个按键,可以正常显示按键码,但是延时结束后,仍然显示,直到按新的按键,才会发生变化。可以帮忙修改一下么?谢谢了!
另外,新手,尽量讲的详细一些,谢谢!
Proteus仿真电路以及汇编、C程序
ourdev_556000.rar(文件大小:19K) (原文件名:按键中断仿真.rar)
Proteus仿真图片
(原文件名:仿真.jpg)
C源程序,这些都包含在附件中,这个是给不想下附件的看的。
//=============头文件及配置===================
#include<pic.h>
__CONFIG(HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//============全局变量====================
unsigned char KeyCode[8];
unsigned char KeySaved=0x00;
unsigned char KeyCurrent=0x00;
//===========函数声明======================
void KeyCheck(unsigned char KeySaved,unsigned char KeyCurrent);
void Delay(void);
//===========主函数========================
main()
{
TRISB=0xF0;//PORTB高4位输入,低4位输出
TRISD=0x00;//PORTD全输出
PORTD=0x00;//PORTD清零
PORTB=0x00;//PORTB清零,PORTB=B'11110000'
RBPU=0;//在C里,NOT_RBPU位即RBPU位,开启PORTB的内部弱上拉
RBIE=1;//开启PORTB端口引脚状态变化中断
GIE=1;//开启总中断
while(1)
{
PORTD=0x00;
PORTB=0x00;
KeyCheck(KeySaved,KeyCurrent);//按键检测
}
}
//==============================================
void interrupt RbInt(void)
{
unsigned char ScanCode=0xEF;//定义按键扫描
unsigned int k;
if(RBIE && RBIF)//判断中断使能和中断标志位
{
RBIF=0;//清零中断标志位
if((PORTB & 0xF0)!=0xF0)//如果有按键按下
{
for(k=0;k<5;k++)
{
PORTB=ScanCode;//输出初始扫描值,PORTB的引脚上逻辑电平高4为不变
if((PORTB & 0xF0)!=0xF0)
{
KeyCode[KeyCurrent]=PORTB;
break;
}
else
{
ScanCode=ScanCode>>1;//扫描码循环右移,这个移的乱七八糟的
//不知道是仿真的问题,还是移位的问题
//原理就是低4为依次循环输出0,而其他位为高
}
}
}
KeyCurrent++;//当前按键存储偏移位置加1
KeyCurrent=KeyCurrent & 0x07;//确保按键存储偏移位置小于8
}
}
//==============================================
void KeyCheck(unsigned char KeySaved,unsigned char KeyCurrent)//按键检测函数
{
if(KeyCurrent!=KeySaved)//如果当前按键偏移位置和已有的按键偏移位置不相等,则有新的按键
{
PORTD=KeyCode[KeySaved];//读保存的按键码
Delay();//延时显示
KeySaved = KeyCurrent;//已有按键偏移位置加1,与当前按键偏移位置同步
//KeySaved = KeySaved & 0x07;//确保按键已存储偏移位置小于8
}
else PORTD=0x00;
}
//==============================================
void Delay(void)//延时
{
int n;
for(n=0;n<=5000;n++)
continue;
}
//==============================================
-----------------------------------------------------------------------
汇编是找到键值,然后显示,延时,关显示;而你的程序是如有按键,显示,延时;若没按键关显示。else PORTD=0x00;
显示按键扫描码-------------
MOVF INDF,W ;读取INDF所指向的地址(当前按键扫描码存储地址)
MOVWF PORTD ;把扫描码地址输出给PORTD
CALL DELAY ;延时显示按键扫描码
CLRF PORTD ;清零PORT
我有疑问,请问一下 for(k=0;k<5;k++) 。这个是循环5次。及K为0,1,2,3,4,都会执行的,而你的按键扫描要移位4次。
void KeyCheck(unsigned char KeySaved,unsigned char KeyCurrent)//按键检测函数
{
if(KeyCurrent!=KeySaved)//如果当前按键偏移位置和已有的按键偏移位置不相等,则有新的按键
{
PORTD=KeyCode[KeySaved];//读保存的按键码
Delay();//延时显示
KeySaved = KeyCurrent;//已有按键偏移位置加1,与当前按键偏移位置同步
//KeySaved = KeySaved & 0x07;//确保按键已存储偏移位置小于8
PORTD=0x00;//就算加了这句,也还是显示按键的值啊,奇怪了。
}
else PORTD=0x00;
}
you should check to see how to clear interrupt-on-change flags - read the datasheet on that.
you could also refine your key_scan routine.
it is not very efficient. a simpler approach is to output 0x0f on portb,
read it back; and then output 0xf0 on portb, read it back.
you can figure out the keys pressed by comparing the two reads, :)
-----------------------------------------------------------------------
你的意思是用PORTB输出0x0F,然后读回来,然后再输出0xF0,再读回来,然后比较两组读回来的数的不同?
我试试。
#include<pic.h>
__CONFIG(HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//============全局变量====================
unsigned char KeyHigh=0x00;
unsigned char KeyLow=0x00;
unsigned char KeyCode=0x00;
//===========函数声明======================
void KeyCheck(void);
void Delay(void);
//===========主函数========================
main()
{
TRISB=0xF0;//PORTB高4位输入,低4位输出
TRISD=0x00;//PORTD全输出
PORTD=0x00;//PORTD清零
PORTB=0x00;//PORTB清零,PORTB=B'11110000'
RBPU=0;//在C里,NOT_RBPU位即RBPU位,开启PORTB的内部弱上拉
RBIE=1;//开启PORTB端口引脚状态变化中断
GIE=1;//开启总中断
RBIF=0;
while(1)
{
TRISB=0xF0;
PORTD=0x00;
KeyCheck();//按键检测
}
}
//==============================================
void interrupt RbInt(void)
{
unsigned char i;
if(RBIE & RBIF)//判断中断使能和中断标志位
{
GIE=0;
RBIE=0;
RBIF=0;//清零中断标志位
PORTB=0xF0;//低4位全输出零,若有按键按下,则高4位有0读回
for(i=0;i<16;i++);
KeyHigh=~PORTB;//读回取反
KeyHigh=KeyHigh & 0xF0;//保留高4位,低4位清零
TRISB=0x0F;
PORTB=0x0F;//若有按键,则低4位有0读回。
for(i=0;i<16;i++);
KeyLow=~PORTB;
KeyLow=KeyLow & 0x0F;
KeyCode=KeyHigh | KeyLow;
TRISB=0xF0;
PORTB=0x00;
PORTD=KeyCode;
RBIE=1;
GIE=0;
}
}
//==============================================
void KeyCheck(void)//按键检测函数
{
if((PORTB & 0xF0)!=0xF0)//如果高4位不全为1,则有新的按键
{
PORTD=KeyCode;
Delay();
}
else PORTD=0x00;
}
//==============================================
void Delay(void)//延时
{
int n;
for(n=0;n<=5000;n++)
continue;
}
//===============================================
不行啊,这样写的话,只有按着按键的时候才会显示按键码。
而且,仿真的时候,PORTB的高4位和低4位不停的在1111和0000之间循环着。
睡觉去了,明天再研究。
感觉PIC的资料好少啊,51的就多一些。
一周热门 更多>