打印

请教我用PIC16f77做的键盘中断扫描程序有错吗 同时按4个键死

[复制链接]
4807|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yjypmypm|  楼主 | 2009-2-24 20:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
4*4键盘
中断方式为PROTB口的RB7-RB4电平变化中断;
RB7-RB4接行扫描线,RB3-RB0接列扫描; 具体电路见张明峰的《PIC单片机入门与实战》第172页。
  
出现的问题是。能正常显示扫描码(外接了一个带字库的LCD屏。但是同时按下一行(4个)按键程序就死了(LCD屏上的扫描码不刷新了  ——没开看门狗)。
请前辈指点下,谢谢了。

//端口的初始化;
void port_init()
{
  ADCON1=0X07;   // 初始化I/O,使其工作在数字I/O状态
 TRISA = 0xFF; //ff;  0 out; 1 in

//初始化RB口为电平变化中断
  TRISB = 0xF0; //RB口设置为输入,低输出;
  RBPU=0;      //使用RB口弱上拉
  PORTB=0;     //PORTB 低4位输出0
  INTCON=0;    // 清除INTCON 所有中断禁止;
  RBIE=1 ;       //允许RB口电平变化中断;
  

//****在这里没有打开全局中断***************
 TRISC = 0x3E; //fe "0011 1110"
 TRISD = 0x00; 
 TRISE = 0x01; //df;   "0000 0001"  busy(输入) req(输出)
 }  





static uchar key_t,key_i;
uchar key_a=200;
void interrupt INTS(void)
{
 if(RBIE && RBIF)
   {
    if(PORTB!=0xf0)
      { 
          
       while(key_a--); //有键按下消抖后再判断;
        
          if(PORTB!=0xf0)
           {
               
             PORTB=0xfe;     //准备扫描码;
              NOP();
              NOP();
             for(key_i=0;key_i<4;key_i++)    //最多扫4次;
              {
                 if((PORTB&0xf0)!=0xf0)
                  {key=PORTB;             //得到的扫描码。
                    press++;
                   break;
                   } 
                 else 
                   {CARRY=1;              //置位进位标志。
                    PORTB=PORTB<<1;
                    NOP();
                    NOP();
                   }
                }
              
              
           }
           else
              {
              interfere++; //可能干扰;
               }

      }
     else 
         {
          rebound++;//按键弹起;
          }
      
   }
    end:
   enter++;  //中断进入次数;
       


PORTB=0;  // 清0 RB口;进行下一次扫描;
key_t=PORTB;  //读一次RB口清中断标志;
RBIF=0;   //清软件中断标志
GIE=1;  //开中断;
}  
沙发
HotC51| | 2009-2-24 20:55 | 只看该作者
板凳
yjypmypm|  楼主 | 2009-2-24 21:09 | 只看该作者

虽然键盘延时有点短,但显示的扫描码没出过问题。

    虽然键盘延时有点短,但显示的扫描码没出过问题.调试时用过整型变量, uint  key_a=2000;  (值200也是如此) 来延时2MS,但按下按键程序停了少说也有1秒(LCD不停地显示字符),后来改为uchar型变量就很快了。  不知道为什么。编译器问题? 编译环境MPLAB7.20+PICC8.05**版;

使用特权

评论回复
地板
兰天白云| | 2009-2-25 08:39 | 只看该作者

一:
static uchar key_t,key_i;

void interrupt INTS(void)
{
uchar key_a=200;     //放在这里合适
if(RBIE && RBIF)
   {
    if(PORTB!=0xf0)


二:

for(key_i=0;key_i<4;key_i++)    //最多扫4次;
              {
                 if((PORTB&0xf0)!=0xf0)
                  {key=PORTB;             //得到的扫描码。
                    press++;
                   break;
                   } 
                 else 
如果一行键都按下,key值不对

使用特权

评论回复
5
yjypmypm|  楼主 | 2009-2-27 00:43 | 只看该作者

谢谢兰天前辈的指点。

我又对程序做了以下修改。
扫描方式完全根据张工给出的汇编语言“翻译”出来的;
  现在同时按下一行4个键后(按下任意2或3个键没有什么问题),程序不哪么容易死了(有时还会死),只是按下4个键进入中断次数不断增加。(一直不停的进入中断)。不知道为什么?

   程序死我估计是跑飞了。
    向显示屏发送数据的函数
   void send (uchar dat)               //写命令或数据
{
  while(busy==1);   //估计程序飞到这里了;
  bus=dat;
   NOP();
   NOP();
  req=1;
 while(busy==0);//或这里;
  req=0;
  return;
}




新的键盘处理程序

#include <pic.h>
#define SLEEP()  asm("sleep")
#define NOP()    asm("nop")
#define clrwdt() asm("clrwdt")


#define uchar  unsigned char  
#define uint   unsigned int

#include "include.h"
extern uchar key;


extern bank1 uint interfere;
extern bank1 uint press;
extern bank1 uint rebound;
extern bank1 uint enter;
extern bank1 uint zero;

static uchar key_t,key_i;



void interrupt INTS(void)
{

  uchar key_a=200,i=1;
    while(key_a--);      //先消抖;         
  if(RBIE && RBIF)
   {
    if((PORTB&0xf0)^0xf0)//屏蔽低4位,并取反,判断高4位是否有1;有1即键按下
      { 
         PORTB=0x0e;            //有键按下,则置打描码,查询
              NOP();
              NOP();
              while(i)             // i 的值为PROTB取反,在PROTB左移8次后i的值将变为0退出循环。张工比较高明的做法 呵呵。
                   { 
                     i=PORTB^0xff;  //获得i的值;为PROTB的值取反;
                     if(i&0xf0)     //如果屏蔽低4位,高位有1,则找到按键。
                       {key=PORTB;  //获得按键;
                        
                        press++;    //显示按下的次数用以显示;
                        break;      //获得按键后,退出循环;
                        }
                        else
                            {
                             CARRY=1;  //为下一个扫描码,置进位标志;
                             
                             PORTB=PORTB<<1;  //扫描下一列
                             NOP();
                             NOP();
                             }
                     }

      }
     else 
         {
          rebound++;  //记录弹起次数,用以显示;
          }
      
   }
    
enter++;             //记录中断次数,用以显示;
       


PORTB=0;          //为下一次按键做准备;
key_t=PORTB;  //读一次RB口清硬件中断标志;
RBIF=0;       //清硬件中断标志;
GIE=1;         //开中断
}  


兰天前辈说的 key值不对,是指哪里不对。


使用特权

评论回复
6
yjypmypm|  楼主 | 2009-3-2 22:44 | 只看该作者

困扰一周了,原因找出来了

最后一句
GIE=1;         //开中断 
在中断还没退出时又进入中断,

使用特权

评论回复
7
backupyan| | 2009-3-3 23:01 | 只看该作者

真不容易啊。

使用特权

评论回复
8
yjypmypm|  楼主 | 2009-3-4 01:04 | 只看该作者

虽然现在按一行4个键不死机了(按一列只有一个扫描码.)

但同时按下一行4个键,老是不停的进入中断。1秒可能进入上百次不知道问题出在哪。
不可能是按键抖动,因为同是按一行3个键都没事。
继续困扰中。。。。

使用特权

评论回复
9
yjypmypm|  楼主 | 2009-3-15 13:17 | 只看该作者

自已顶下。

没有哪位前辈遇到这个问题吗。。。。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

21

帖子

0

粉丝