📄 keyled.c
字号:
#include <stdio.h>
#include <reg51all.h>
#include <intrins.h>
#define SEGCODE P1 // 数码管字型码由P1输出,A~H对应D7~D0,0点亮,1熄灭
#define POSCTRL0 P34
#define POSCTRL1 P35
#define LS0 P30 // 位置码同时作为键盘列扫描码,共8列,2行
#define LS1 P31 // 行扫描由P36,P37完成,D0~D7对应1~8列,为0表示有键按下
#define JCON0 P32 //继电器选通
#define JCON1 P33 //继电器选通
#define BRAY P37
unsigned char Row,Col; // 按键的行列值
unsigned char ucTH,ucTL; // 定时器初值
unsigned char start,set,position,ii; //按键设置标记和选路标记
unsigned char hnum,lnum; //定时数的高位和低位
unsigned char count[2]; //定时数
int jj; //中断计数
unsigned char logo; //倒计时时间到标记
/*******************************************************************************
键盘连接方式:
C0 C1
R0 -|---|- P30
R1 -|---|- P31
P34 P35
*******************************************************************************/
// 根据A~H对应D7~D0的关系设定0~F的字形码
unsigned char code SEGTABLE[] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x5f,0x7c,0x58,0x5e,0x79,0x71};
unsigned char CurrRow[2],CurrCol[2],LastRow[2],LastCol[2]; // 存放当前和前次两行和两列扫描码
//******************************************************************************
// 函数名:T0ISR
// 功 能:2.5ms中断服务程序
// 作 者:mudfish 2005-10-31 10:12
// 注 释:
//******************************************************************************
void T0ISR(void) interrupt 1
{
unsigned char i,j,k;
// 重新设置定时常数
TH0 = ucTH;
TL0 = ucTL;
TR0 = 1;
if(logo==1) //倒计时时间到标记
BRAY=1; //鸣叫1秒
else BRAY=0; //关闭鸣叫
// 先进行键盘扫描
SEGCODE = 0xff; // 关闭所有段显示
CurrRow[0] = 0;
CurrRow[1] = 0;
CurrCol[0] = 0;
CurrCol[1] = 0;
POSCTRL0 = 0; // 当前扫描列送0
POSCTRL1 = 1;
LS0 = 1;
_nop_();_nop_();_nop_();_nop_();
if(LS0 == 0)
{
CurrRow[0] =1;
CurrCol[0]=1; // 该位置0
}
LS1 = 1;
_nop_();_nop_();_nop_();_nop_();
if(LS1 == 0)
{
CurrRow[1] =1;
CurrCol[0]=1; // 该位置1
}
POSCTRL0 = 1;
POSCTRL1 = 0; // 当前扫描列送0
LS0 = 1;
_nop_();_nop_();_nop_();_nop_();
if(LS0 == 0)
{
CurrRow[0] =1;
CurrCol[1]=1; // 该位置1
}
LS1 = 1;
_nop_();_nop_();_nop_();_nop_();
if(LS1 == 0)
{
CurrRow[1] =1;
CurrCol[1]=1; // 该位置1
}
// 扫描完成
// 开始按键处理
Row = 0xff; // 缺省无按键状态
Col = 0xff;
for(j=0;j<2;j++)
{
if( (CurrRow[j]^LastRow[j]) != 0) // 按键状态有变化
{
for(i=0;i<2;i++)
{
if( LastCol[i]== 1 )
{
Row = j; // 本次扫描按键状态有变化且上次为按下
Col = i; // 说明本次为按键松开,有效
break; // 每次只处理一个按键
}
}
}
if( (Row!=0xff) && (Col!=0xff) ) break; // 每次只处理一个按键
}
for(j=0;j<2;j++)
{
LastRow[j] = CurrRow[j];
LastCol[j]=CurrCol[j]; // 将本次扫描码保存到上次扫描码
}
//加法按键
if(Row==0 && Col==0)
{
count[position]=count[position]+1; //加1
if(count>99)
count[position]=0; //值0~99
BRAY=1; //鸣叫
}
//减法按键
if(Row==0 && Col==1)
{
count[position]=count[position]-1; //减1
if(count<0) //值0~99
count[position]=99;
BRAY=1; //鸣叫
}
//选路按键
if(Row==1 && Col==0)
{
set=1; //设置标志
start=0;
position=(position+1)%2; //选路
BRAY=1; //鸣叫
}
//开始倒计时按键
if(Row==1 && Col==1)
{
set=0;
start=1; //开始标记
JCON0=1; //继电器0选通
JCON1=1; //继电器1选通
BRAY=1; //鸣叫
}
//设置倒计时间时数码管的显示处理
if(set==1)
{
hnum=count[position]/10; //高位
lnum=count[position]%10; //低位
POSCTRL0=1; //显示高位
POSCTRL1=0;
SEGCODE=SEGTABLE[hnum];
_nop_();_nop_();_nop_();_nop_();
POSCTRL0=0;
POSCTRL1=1; //显示低位
SEGCODE=SEGTABLE[lnum];
}
//开始倒计后的显示处理和计时到处理
if(start==1)
{
hnum=count[ii]/10; //高位
lnum=count[ii]%10; //低位
POSCTRL0=1; //显示高位
POSCTRL1=0;
SEGCODE=SEGTABLE[hnum];
_nop_();_nop_();_nop_();_nop_();
POSCTRL0=0;
POSCTRL1=1; //显示低位
SEGCODE=SEGTABLE[lnum];
jj++;
if(jj>200) ii=(ii+1)%2; //0.5秒 显示另外一路
if(jj>400) //1秒
{
jj=1;
logo=0; //1秒重设标记
for(k=0;k<2;k++)
{
count[k]=count[k]-1; //1秒 减1
if(count[k]==0) //计时到
{
logo=1; //倒计时间到标记
if(k==0)
JCON0=0; //继电器0该路关闭
if(k==1)
JCON1=0; //继电器1该路关闭
}
}
}
}
}
void main(void)
{
position=0; //选第一路
count[0]=0; //第一路初值为0
count[1]=0; //第二路初值为0
JCON0=0; //关闭继电器0
JCON1=0; //关闭继电器1
ii=1;
jj=1;
EA = 0; // 停止所有中断
ucTH = (65536-22118400/12/400)/256; // 计算2.5ms定时的时间常数(22.1184M OSC)
ucTL = (65536-22118400/12/400)%256;
TMOD = 0x01; // T0:模式1,16位定时器
TH0 = ucTH; //定时器赋初值
TL0 = ucTL;
ET0 = 1; // T0允许中断
TR0 = 1; //开始计数
EA = 1; //开所有的中断
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -