|
/* ****************************************************************
** 功能描述: 采用B口电平变化中断查键方式识别键盘,按下K1键时第一个数码管数码管显示1,按下K2键时显示2,按下K3键时显示3,按下K4键时显示4
*************************************************************** */
#include "pic18.h" /* PIC18系列的头文件 */
const char table[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90, 0x88,0x83,0xc6,0xa1,0x86,0x8e};
/* 不带小数点的显示段码表,依顺序为0-F共16个 */
const char table0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
/* 带小数点的0-9显示段码表 */
unsigned char key=0; // 按键键值,=1表示1号键按下,…,=4表4号键按下
unsigned char PORTB_keyflag=0; //=1有键按下,=0无按按下
/* ****************************************************************
** 函 数 名: initial()
** 功能描述: 系统初始化子程序,放在程序首部
*************************************************************** */
void initial()
{
INTCON=0x00; /* bit7-bit0:关总中断 */
ADCON1=0X07; /* 设置数字输入输出口 */
PIE1=0; /* PIE1 的中断不使能 */
PIE2=0; /* PIE2 的中断不使能 */
PIE3=0; /* PIE3 的中断不使能 */
}
/* ****************************************************************
** 函 数 名: SPIinitial()
** 功能描述: SPI输出初始化子程序
*************************************************************** */
void SPIinitial()
{
TRISA=TRISA&0xdf; /* 设置RA5输出74HC595锁存信号的引脚为输出 */
TRISC=TRISC&0xd7; // SDO(RC5)引脚为输出,SCK(RC3)引脚为输出
SSPCON1=0x30; // SSPEN=1;CKP=1,FOSC/4
SSPSTAT=0xC0; // 时钟下降沿发送数据
SSPIF=0; // 清除SSPIF标志
}
/* ****************************************************************
** 函 数 名: SPILED()
** 功能描述: SPI传输数据(发送数据)子程序
*************************************************************** */
void SPILED(char data)
{
SSPBUF=data; /* 启动 SPI 发送 */
do
{
;
}while(SSPIF==0); /* 等待SPI 发送完成 */
SSPIF=0; /* 清SPI 发送完成标志 */
}
/* ****************************************************************
** 函 数 名: display(unsigned char data)
** 功能描述: 在第8个数码管显示数据,其余7个不显示(全暗)
*************************************************************** */
void display(unsigned char data)
{
unsigned char k;
RA5=0; /* 准备锁存显示数据 */
data=table[data]; /* 查与显示数据对应的段码 */
SPILED(data); /* 发送显示段码 */
for(k=1;k<8;k++)
{
SPILED(0Xff); /* 发送当前数码管不显示段码 */
}
RA5=1; /* 给锁存信号,显示数字 */
}
/* ****************************************************************
** 函 数 名: PORTB_Interrupt_Initial()
** 功能描述: PORTB口电平变化中断初始化
*************************************************************** */
void PORTB_Interrupt_Initial()
{
TRISB=TRISB|0xf0; // PORTB工作在电平变化中断方式,bit7-bit4设置为输入
INTCON=INTCON|0x08; // RBIE=1,使能RB电平变化中断
INTCON=INTCON&0xfe; // RBIF=0,清RB电平变化中断标志
INTCON2=INTCON2&0x7f; // 在电平变化中断方式下,B口电平弱上拉,RBPU=0
RBIP=0; // RB电平变化中断为低优先级中断
TRISB1=0; // 设置K1为输出
TRISA3=0; // 设置K2为输出
TRISE0=0; // 设置K3为输出
TRISE1=0; // 设置K4为输出
RB1=0; /* 设置K1-K4平时为低电平,4个键的另一端均接到
RB4上,平时RB4为高电平(上拉),有键
按下后,被K1-K4下拉为低电平,产生中断 */
RA3=0;
RE0=0;
RE1=0;
PORTB=PORTB; // 设置PORTB口电平变化初始条件
}
/* ****************************************************************
** 函 数 名: DELAY_PORTB_Interrupt()
** 功能描述: PORTB口电平变化中断查键延时防抖子程序
*************************************************************** */
void DELAY_PORTB_Interrupt()
{
unsigned int i;
for(i = 553; i>0;i--)
i=i;
}
/* ****************************************************************
** 函 数 名: KEYSCAN_PORTB_Interrupt()
** 功能描述: PORTB口电平变化中断查键键扫描子程序
*************************************************************** */
void KEYSCAN_PORTB_Interrupt()
{
if(RB4==0) // 有键按下
{
DELAY_PORTB_Interrupt();// 若有键按下,则软件延时防抖
if (RB4==1) return; // 防抖后无键按下,是抖动,不做按键处理,返回
//以下为防抖后仍有键按下的查键值
RB1=0; // 设置K1为低电平
RA3=0; // 设置K2为低电平
RE0=1; // 设置K3为高电平
RE1=1; // 设置K4为高电平,判断按键是否在K1、K2之间
if(RB4==0) // 按键是k1k2中的一个
{
RA3=1; // (只有)K1为低电平
if(RB4==0)key=1; // 仅K1为低电平时RB4被下拉,K1键按下
else key=2; // K1k2为低电平RB4被下拉,K1没按下,是K2按下
PORTB_keyflag=1; //新键按下标志,=1表示有新键按下
RB1=0; //设置电平变化产生中断的初始条件
RA3=0;
RE0=0;
RE1=0;
PORTB=PORTB;
return;
}
RB1=1; // 不是在K1k2间按下,查K3k4,设K1K2为高电平,不查K1k2
RA3=1;
RE0=0; // 设置K3为低电平
RE1=0; // 设置K4为低电平
if(RB4==0) // 若有键按下(无键按下可视为防抖)
{
RE1=1; // 仅设置K3为低电平
if(RB4==0)key=3; // 仅K3为低电平时RB4被下拉,K3键按下
else key=4; // K3k4为低电平RB4被下拉,K3没按下,是K4按下
}
PORTB_keyflag=1; //新键按下标志,=1表示有新键按下
}
RB1=0; //设置电平变化产生中断的初始条件
RA3=0;
RE0=0;
RE1=0;
PORTB=PORTB;
}
/* ****************************************************************
** 函 数 名: interrupt low_priority LOW_ISR()
** 功能描述: 低优先级中断子程序:PORTB口RB电平变化中断
*************************************************************** */
void interrupt low_priority LOW_ISR()
{
if(RBIF==1) //PORTB口RB电平变化中断
{
KEYSCAN_PORTB_Interrupt(); //查键子程序
RBIF=0; //清中断标志
}
}
main()
{
initial();
SPIinitial(); /* spi显示初始化 */
PORTB_Interrupt_Initial(); // PORTB口电平变化中断初始化
IPEN=1; // 使能中断高低优先级
INTCON=INTCON|0xc0; //打开总中断和外围接口中断
display(0XFF); /* 清数码管当前显示即清屏 */
while(1)
{
if(PORTB_keyflag==1) // 若有按键按下
{
display(key); //显示按键键值(1-4)
PORTB_keyflag=0; //清按键按下标志
}
}
}
|
|