初始化
(把led和蜂鸣器啥的先关了)
通过操作P25 P26 P27 选择P0控制的设备
void init_system() //初始化
{
select_HC138(5);
P0 = 0x00;
select_HC138(4);
P0 = 0xFF; //关闭LED
}
void select_HC138(uchar n)
{
switch(n)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xA0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xC0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xE0;
break;
}
}
配置定时器,打开中断
(总中断在main里面开)
这里直接复制烧录软件里生成的代码(1毫秒)
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
}
中断用来刷新数码管
void interruptT0() interrupt 1
{
TL0 = 0x18;
TH0 = 0xFC;
smg_scan();
}
数码管刷新
uchar code led_code[11] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //0-9
0xbf //小横杆——led_code[10]
// 若要加小数点则 led_buff -= 128;
};
uchar led_buff[8] = {0};//用来存放数码管要显示的数据
void smg_show(uchar dat, uchar pos) //dat个位数,pos数码管位置
{
P0 = 0xff; //消隐
select_HC138(6);
P0 = 0x01 << (pos);
select_HC138(7);
P0 = led_code[dat];
}
void smg_scan()
{
static uchar i = 0;
smg_show(show_buff[i], i);
i++;
if(i==8) i=0;
}
矩阵按键扫描
这里如果用头文件 reg52.h
是没有P4的
所以用 STC15F2K60S2.h
sbit y1 = P3^0;
sbit y2 = P3^1;
sbit y3 = P3^2;
sbit y4 = P3^3;
sbit x1 = P4^4;
sbit x2 = P4^2;
sbit x3 = P3^5;
sbit x4 = P3^4;
思路是
x置1,y置0, 判断 x 状态,
若x有0,则有按键按下
短暂延时后(消抖),
再次判断 x 状态,确认按键被按下
依次判断x1-4状态,获取按键的列号
x置0,y置1, 判断 y 状态,
获取按键行号
松手检测
uchar key_scan()
{
uchar key_code;
P3 &= 0xF0; x1=1;x2=1;x3=1;x4=1; //y置0,判断x
if(!(x1&&x2&&x3&&x4)) //检测到有按键按下时
{
delay(100);
if(!(x1&&x2&&x3&&x4))
{
if(x1==0) key_code=1;
else if(x2==0) key_code=2;
else if(x3==0) key_code=3;
else if(x4==0) key_code=4; //判断列
x1=0;x2=0;x3=0;x4=0; P3 |= 0x0F; //x置0,判断y
if(y1==0) key_code += (1*10);
else if(y2==0) key_code += (2*10);
else if(y3==0) key_code += (3*10);
else if(y4==0) key_code += (4*10);
while(y1==0||y2==0||y3==0||y4==0); //松手检测
count_key++;
return key_code;
}
}
return 0;
}
主函数
void main()
{
uchar n=0;
init_system();
Timer0Init();
EA = 1;
while(1)
{
n = key_scan();
if(n) //n不是0,则有按键按下,刷新数码管显示
{
led_buff[0] = n/10;
led_buff[1] = n%10;
}
}
}