1、1ms定时中断T0,控制数码管显示
(1) 关于中断
关于定时中断的初始化函数可直接在STC-ISP软件上生成,如下图所示:
注意:初始化函数中并没有打开EA和ET0,需要自己加上。
(2)关于数码管显示:
数码管段码:
segCode[0]~segCode[9]为0~9的段码(不带小数点);
segCode[10]~segCode[19]为0~9的段码(带小数点);
segCode[20]为数码管全灭的代码。
uchar segCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //0~9的段码(不带小数点)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
数码管显示数组:
uchar segVal[] = {1,2,3,4,11,12,13,14}; //数码管初始化显示1 2 3 4 1. 2. 3. 4.
直接更改数组里面的值便可以控制数码管显示,例如
让数码管的第0位显示数字8:
segVal[0]= 8;
让数码管的第1位显示数字8(带小数点):
segVal[1] = 18;
总代码如下:
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sfr AUXR = 0x8e;
uchar segCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //0~9的段码(不带小数点)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={1,2,3,4,11,12,13,14}; //数码管初始化显示1 2 3 4 1. 2. 3. 4.
void SelectHC573(uchar val)
{
switch(val)
{
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;
default: P2 = (P2 & 0x1f); break;
}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
SelectHC573(5);
P0 = 0xbf; //由于不同板子的引脚接法不同,此时的初始值也不同
SelectHC573(4);
P0 = 0xff; //LED全灭
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
uchar segFlag = 0;
void ServiceTimer0() interrupt 1
{
uchar pushp0,pushp2;
pushp0 = P0;
pushp2 = P2;//入栈
SelectHC573(6);
P0 = (0x01<<segFlag);
SelectHC573(7);
P0 = segCode[segVal[segFlag]];
segFlag++;
if(segFlag == 8) segFlag = 0;
P2 = pushp2;//出栈
P0 = pushp0;
}
void main()
{
InitSystem();
Timer0Init();
while(1)
{
;
}
}
2、1ms定时中断T0,检测按键按下(独立按键)
当S4按下时,数码管第0位显示数字0;当S5按下时,数码管第0位显示数字1;
当S6按下时,数码管第0位显示数字2;当S7按下时,数码管第0位显示数字3;
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sfr AUXR = 0x8e;
uchar segCode[25]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //0~9的段码(不带小数点)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={20,20,20,20,20,20,20,20}; //数码管初始化显示1 2 3 4 1. 2. 3. 4.
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
void SelectHC573(uchar val)
{
switch(val)
{
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;
default: P2 = (P2 & 0x1f); break;
}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
SelectHC573(5);
P0 = 0xbf; //由于不同板子的引脚接法不同,此时的初始值也不同
SelectHC573(4);
P0 = 0xff; //LED全灭
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
uchar segFlag = 0;
uchar keySta[] = {1,1,1,1}; //当前按键状态
uchar keyBack[] = {1,1,1,1};//按键值备份,保存前一次的值(上一次的按键状态)
uchar keyBuf[] = {0xff,0xff,0xff,0xff};
void ServiceTimer0() interrupt 1
{
uchar pushp0,pushp2,k;
pushp0 = P0;
pushp2 = P2;//入栈
//数码管
SelectHC573(6);
P0 = (0x01<<segFlag);
SelectHC573(7);
P0 = segCode[segVal[segFlag]];
segFlag++;
if(segFlag == 8) segFlag = 0;
//按键检测
keyBuf[0] = (keyBuf[0]<<1) | S4;
keyBuf[1] = (keyBuf[1]<<1) | S5;
keyBuf[2] = (keyBuf[2]<<1) | S6;
keyBuf[3] = (keyBuf[3]<<1) | S7;
for(k=0; k<4; k++)
{
if(keyBuf[k] == 0x00)
keySta[k] = 0;
else
keySta[k] = 1;
}
P2 = pushp2;//出栈
P0 = pushp0;
}
void main()
{
InitSystem();
Timer0Init();
while(1)
{
//S4
if(keySta[0] != keyBack[0]) //当前值与前次值不相等说明此时按键有动作(按下或弹起)
{
if(keySta[0] == 0) //如果这一次值为 0,则说明当前是按下动作
{
segVal[0] = 0; //数码管第0位显示0
}
keyBack[0] = keySta[0]; //更新前一次的备份
}
//S5
if(keySta[1] != keyBack[1])
{
if(keySta[1] == 0)
{
segVal[0] = 1;
}
keyBack[1] = keySta[1];
}
//S6
if(keySta[2] != keyBack[2])
{
if(keySta[2] == 0)
{
segVal[0] = 2;
}
keyBack[2] = keySta[2];
}
//S7
if(keySta[3] != keyBack[3])
{
if(keySta[3] == 0)
{
segVal[0] = 3;
}
keyBack[3] = keySta[3];
}
}
}
3、1ms定时中断T0,检测按键按下(矩阵键盘)
当按键按下时,数码管第0位显示行(0~3),数码管第1位显示显示列(0~3),例如,当第0行第1列有按键按下时,数码管第0位显示0,第1位显示1。在这个代码里用的是15的头文件STC15F2K60S2.h,此时不用单独定义AUXR寄存器。
#include "STC15F2K60S2.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
//sfr AUXR = 0x8e;
uchar segCode[25]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //0~9的段码(不带小数点)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={20,20,20,20,20,20,20,20}; //数码管初始化显示1 2 3 4 1. 2. 3. 4.
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L4 = P3^4;
sbit L3 = P3^5;
sbit L2 = P4^2;
sbit L1 = P4^4;
void SelectHC573(uchar val)
{
switch(val)
{
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;
default: P2 = (P2 & 0x1f); break;
}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
SelectHC573(5);
P0 = 0xbf; //由于不同板子的引脚接法不同,此时的初始值也不同
SelectHC573(4);
P0 = 0xff; //LED全灭
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
uchar segFlag = 0;
uchar keySta[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //当前按键状态
uchar keyBack[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};//按键值备份,保存前一次的值(上一次的按键状态)
uchar keyBuf[4][4] = {{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
uchar hang = 0; //扫描行标志位
void ServiceTimer0() interrupt 1
{
uchar pushp0,pushp2,k;
pushp0 = P0;
pushp2 = P2;//入栈
//数码管
SelectHC573(6);
P0 = (0x01<<segFlag);
SelectHC573(7);
P0 = segCode[segVal[segFlag]];
segFlag++;
if(segFlag == 8) segFlag = 0;
switch(hang)//根据扫描行标志位,释放当前输出引脚,拉低下次的输出引脚
{
case 0: H1 = 0; H4 = 1; break;
case 1: H2 = 0; H1 = 1; break;
case 2: H3 = 0; H2 = 1; break;
case 3: H4 = 0; H3 = 1; break;
}
//将一行的 4 个按键值移入缓冲区,hang=0,1,2,3
keyBuf[hang][0] = (keyBuf[hang][0]<<1) | L1;
keyBuf[hang][1] = (keyBuf[hang][1]<<1) | L2;
keyBuf[hang][2] = (keyBuf[hang][2]<<1) | L3;
keyBuf[hang][3] = (keyBuf[hang][3]<<1) | L4;
for(k=0; k<4; k++)//每行 4 个按键,所以循环 4 次
{
if(keyBuf[hang][k] == 0x00) //连续8次扫描值为0,可认为按键已稳定的按下
keySta[hang][k] = 0;
else if(keyBuf[hang][k] == 0xff)//连续8次扫描值为 1,可认为按键已稳定的弹起
keySta[hang][k] = 1;
}
//执行下一次的扫描输出
hang++; //扫描行标志位加一
if(hang == 4) hang = 0;
P2 = pushp2;//出栈
P0 = pushp0;
}
void main()
{
InitSystem();
Timer0Init();
while(1)
{
uchar i,j;
//如果有按键按下,则数码管显示按键值
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
{
if(keySta[i][j] != keyBack[i][j])
{
if(keySta[i][j] == 0) //如果这一次值为 0,则说明当前是按下动作
{
segVal[0] = i; //数码管第0位显示i,即行值
segVal[1] = j; //数码管第1位显示j,即列值
}
keyBack[i][j] = keySta[i][j]; //更新前一次的备份
}
}
}
}
}