专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

PORTB的电平变化中断进行键盘输入

作者:佚名   来源:本站原创   点击数:  更新时间:2008年07月06日   【字体:

//该程序通过PORTB的"电平变化中断"进行键盘的输入,使按下K1键时第一个数码管显示1,按下K2
//键时第一个数码管上显示2,按下K3键时第一个数码管上显示3,按下K4键时第一个数码管上显示4
//对键盘的扫描采用中断方式

#include "p18f458.h"

unsigned  char data;
unsigned  int i;
unsigned  char j;
const char table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0xbf,0x89,0xff};

void InterruptHandlerHigh(void);

/*初始化子程序*/
/* http://www.51hei.com 提供此程序*/
void  initial()
{
 INTCON=0x08;    /*关闭所有中断,B口变位中断允许*/
 INTCON2=0x01;    /*使能B口弱上拉,B口变位中断高优先级*/
 RCONbits.IPEN=1;    /*使能中断优先级*/
 TRISA=0x00;     /*A口设置为输出*/
 TRISB=0XF0;     /*RB1输出,RB4输入*/
 TRISC=0x00;     /*SDO引脚为输出,SCK引脚为输出*/
 TRISE=0x00;     /*E口设置为输出*/
 SSPCON1=0x30;    /*SSPEN=1;CKP=1,FOSC/4*/
 SSPSTAT=0xC0;    /*时钟下降沿发送数据*/
 PIR1=0;      /*清除SSPIF标志*/
 data=0X00;     /*待显示的寄存器赋初值*/ 
 PORTBbits.RB1=0;
 PORTAbits.RA3=0;
 PORTE=0;     /*将K1,K2,K3,K4四条列线置0*/
 PORTB=PORTB;    /*读B口的值,为变位中断创造条件*/ 
}

/*键服务子程序*/ 
void KEYSERVE()
{
 PORTBbits.RB1=0;    /*K1,K2置低电平,K3,K4置高电平*/
 PORTAbits.RA3=0;    /*RB4为0,表示按键为K1,K2中的一个*/
 PORTE=3;     /*RB4为1,表示按键为K3,K4中的一个*/
 if(PORTBbits.RB4==0)
 {
  PORTBbits.RB1=0;   /*K1置低电平,K2置高电平*/
  PORTAbits.RA3=1;   /*RB4为0,表示按键为K1;RB4为1,表示按键为K2*/
  if(PORTBbits.RB4==0) j=0X01;
  else {j=0X02; PORTAbits.RA3=0;}
 }
 else
 {
  PORTEbits.RE0=0;   /*K3置低电平,K4置高电平*/
  PORTEbits.RE1=1;   /*RB4为0,表示按键为K3;RB4为1,表示按键为K4*/
  if(PORTBbits.RB4==0) j=0X03;
  else {j=0X04; PORTEbits.RE1=0;}  
 }
}

/*软件延时子程序*/
void  DELAY()
{
 for(i = 6553; --i ;)
 continue;
}

/*显示子程序*/
void SPILED(char data)
{
 PORTAbits.RA5=0;     /*LACK送低电平,为锁存做准备*/
 SSPBUF=data;      /*启动发送*/
 do
 {
 ;
 }while(PIR1bits.SSPIF==0);   /*等待发送完毕*/
 PIR1bits.SSPIF=0;     /*清除SSPIF标志*/
 PORTAbits.RA5=1;     /*最后给锁存信号,代表显示任务完成*/
}

/*高优先级中断向量*/
#pragma code InterruptVectorHigh=0x08
void InterruptVectorHigh (void)
{
  _asm
    goto InterruptHandlerHigh    /*跳到中断程序*/
  _endasm
}

/*高优先级中断程序*/
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh ()
{
 INTCONbits.RBIF=0;   /*中断标志清0*/  
 DELAY();     /*软件延时*/
 PORTB=PORTB;    /*读PORTB的值,并改变中断发生的条件,可屏蔽*/
        /*一次按键松开时产生的无效的中断,又可以防止按键*/
        /*时间过长发生连续中断*/
 if(PORTBbits.RB4==0)
 {  
  KEYSERVE();    /*进行键盘的识别*/
  PORTBbits.RB1=0;
  PORTAbits.RA3=0;
  PORTE=0;    /*将K1,K2,K3,K4四条列线置0,以防止键扫描时改变*/ 
        /*K1,K2,K3,K4的电平,从而改变中断条件*/
  INTCONbits.RBIF=0;  /*键扫描时可能会产生"电平变化"而使置1,再清除一次*/
        /*RBIF以求避免额外中断*/  
  data=table[j];    /*获得需要送出显示的段码*/
  SPILED(data);
 }
}

/*主程序*/
main()
{
 initial();      /*系统初始化*/
 INTCONbits.GIE=1;    /*总中断允许*/
 while(1)
 {
 }       /*等待中断*/
}
 

关闭窗口