/*
*******************************************************************************
* 文件名:main.c
* 描 述:秒表计数
* 作 者:CLAY
* 版本号:v1.0.0
* 日 期: 2018年2月10日
* 备 注:对应键盘映射的ESC键让秒表复位,回车键让秒表起停。
* S8 -- reset .. S12 -- Start/stop
*******************************************************************************
*/
#include
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
sbit KEY_IN_1 = P3^3;
sbit KEY_IN_2 = P3^2;
sbit KEY_IN_3 = P3^1;
sbit KEY_IN_4 = P3^0;
sbit KEY_OUT_1 = P4^4;
sbit KEY_OUT_2 = P4^2;
sbit KEY_OUT_3 = P3^5;
sbit KEY_OUT_4 = P3^4;
u8 code LedChar[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
u8 LedBuff[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
u8 KeySta[4][4] = {
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
};
u8 code KeyCodeMap[4][4] = { //映射关系是从板子的左往右看
{0x30, 0x37, 0x34, 0x31}, //S4, S5, S6, S7 ==> 数字键0、数字键7、数字键4、数字键1
{0x1B, 0x38, 0x35, 0x32}, //S8, S9, S10, S11 ==> ESC 键 数字键8、数字键5、数字键2
{0x0D, 0x39, 0x36, 0x33}, //S12, S13, S14, S15 ==> 回车键 、数字键9、数字键6、数字键3
{0x27, 0x28, 0x25, 0x26} //S16, S17, S18, S19 ==> 向右键 、向下键 、向左键 、向上键
};
//板子方正之后,正着看就是:
//数字键1、数字键2、数字键3、向上键
//数字键4、数字键5、数字键6、向左键
//数字键7、数字键8、数字键9、向下键
//数字键0、ESC 键 、回车键 、向右键
bit StopwatchRunning = 0; //定义运行标志
bit StopwatchRefresh = 0; //定义是否刷新
u8 DecimalPart = 0;
u16 IntegerPart = 0;
void CloseFucker();
void Timer0Init();
void KeyDriver();
void StopwatchDisplay();
void main()
{
CloseFucker();
Timer0Init();
ET0 = 1;
EA = 1;
LedBuff[0] = LedChar[0];
while (1)
{
if (StopwatchRefresh)
{
StopwatchRefresh = 0;
StopwatchDisplay();
}
KeyDriver();
}
}
void CloseFucker()
{
P2 = (P2 & 0x1F) | 0x80; //关闭LED
P0 = 0xFF;
P2 = 0x00;
P2 = (P2 & 0x1F) | 0xA0; //关闭蜂鸣器和继电器
P0 = P0 & 0xAF;
P2 = 0x00;
}
void Timer0Init() //1毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void ShowNumber(long num)
{
bit flag = 0; //正数 - 0; 负数 - 1;
char k;
u8 buff[8];
if (num < 0)
{
flag = 1;
num = -num;
}
else
{
flag = 0;
}
for (k=0; k<8; k++)
{
buff[k] = num % 10;
num /= 10;
}
// do{
// buff[k++] = num % 10;
// num /= 10;
// }while(num > 0);
for (k=7; k>0; k--)
{
if (buff[k] == 0x00)
{
LedBuff[k] = 0xFF;
}
else
{
break;
}
}
if (flag)
{
if (k<7)
{
LedBuff[k+1] = 0xBF;
}
}
for ( ; k>=0; k--)
{
LedBuff[k] = LedChar[buff[k]];
}
}
void StopwatchDisplay()
{
char k;
u8 buff[4];
LedBuff[0] = LedChar[DecimalPart%10]; //对应后两位是直接显示
LedBuff[1] = LedChar[DecimalPart/10];
buff[0] = IntegerPart % 10;
buff[1] = IntegerPart/10 % 10;
buff[2] = IntegerPart/100 % 10;
buff[3] = IntegerPart/1000 % 10;
for (k=3; k>0; k--)
{
if (buff[k] == 0x00)
{
LedBuff[k+2] = 0xFF;
}
else
{
break;
}
}
for ( ; k>=0; k--)
{
LedBuff[k+2] = LedChar[buff[k]];
}
LedBuff[2] &= 0x7F; //第三个数码管显示小数点。共阳数码管.....
}
void StopwatchReset()
{
StopwatchRunning = 0;
DecimalPart = 0;
IntegerPart = 0;
StopwatchRefresh = 1;
}
void StopwatchAction()
{
if (StopwatchRunning)
StopwatchRunning = 0;
else
StopwatchRunning = 1;
}
void KeyAction(u8 keycode)
{
if (keycode == 0x1B)
{
StopwatchReset();
}
else if (keycode == 0x0D)
{
StopwatchAction();
}
}
void KeyDriver()
{
u8 i, j;
static u8 backup[4][4] = {
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
};
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (KeySta[i][j] != backup[i][j])
{
if (backup[i][j] == 0)
{
KeyAction(KeyCodeMap[i][j]);
}
backup[i][j] = KeySta[i][j];
}
}
}
}
void LedScan()
{
static u8 index=0;
P2 = (P2 & 0x1F) | 0xE0; //消隐
P0 = 0xFF;
P2 = 0x00;
P2 = (P2 & 0x1F) | 0xC0; //位选
P0 = 0x80 >> index;
P2 = 0x00;
P2 = (P2 & 0x1F) | 0xE0; //段选
P0 = LedBuff[index];
P2 = 0x00;
if (index<7)
index++;
else
index=0;
}
void KeyScan()
{
u8 i;
static u8 keyout = 0;
static u8 keybuff[4][4] = {
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
};
switch (keyout)
{
case 0: KEY_OUT_1 = 0; KEY_OUT_4 = 1; break;
case 1: KEY_OUT_2 = 0; KEY_OUT_1 = 1; break;
case 2: KEY_OUT_3 = 0; KEY_OUT_2 = 1; break;
case 3: KEY_OUT_4 = 0; KEY_OUT_3 = 1; break;
default : break;
}
keybuff[keyout][0] = (keybuff[keyout][0] << 1) | KEY_IN_1;
keybuff[keyout][1] = (keybuff[keyout][1] << 1) | KEY_IN_2;
keybuff[keyout][2] = (keybuff[keyout][2] << 1) | KEY_IN_3;
keybuff[keyout][3] = (keybuff[keyout][3] << 1) | KEY_IN_4;
for (i=0; i<4; i++)
{
if ((keybuff[keyout][i] & 0x0F) == 0x0F)
KeySta[keyout][i] = 1;
else if ((keybuff[keyout][i] & 0x0F) == 0x00)
KeySta[keyout][i] = 0;
else{}
}
keyout++;
keyout &= 0x03;
}
void StopwatchCount()
{
if (StopwatchRunning)
{
DecimalPart++;
if (DecimalPart == 100)
{
DecimalPart = 0;
IntegerPart++;
if (IntegerPart == 10000)
{
IntegerPart = 0;
}
}
StopwatchRefresh = 1;
}
}
void InterruptTimer0() interrupt 1
{
static u8 tmr10ms = 0;
TH0 = 0xFC;
TL0 = 0x66;
LedScan();
KeyScan();
tmr10ms++;
if (tmr10ms == 10)
{
tmr10ms = 0;
StopwatchCount();
}
}
体会一下函数式编程的方便,哈哈哈。。。
底层写的好,敲码没烦恼。。。
当然了,上面这个是在写好的模块上直接添加的逻辑,很多冗余的东西,下面展示一个去除冗余的代码。。。
/*
*******************************************************************************
* 文件名:main.c
* 描 述:秒表计数器
* 作 者:CLAY
* 版本号:v1.0.1
* 日 期:
* 备 注:去除冗余
* S17 -- reset .. S18 -- Start/stop
*******************************************************************************
*/
#include
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
sbit KEY_IN_1 = P3^3;
sbit KEY_IN_2 = P3^2;
sbit KEY_IN_3 = P3^1;
sbit KEY_IN_4 = P3^0;
sbit KEY_OUT_4 = P3^4;
u8 code LedChar[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
u8 LedBuff[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0XFF, 0xFF
};
u8 KeySta[4] = { 1, 1, 1, 1};
bit StopwatchRefresh = 1;//这里置1,上电显示0.00
bit StopwatchRunning = 0;
u8 DecimalPart = 0;
u16 IntegerPart = 0;
u8 T0RH;
u8 T0RL;
void ConfigTimer0(u16 ms);
void KeyDriver();
void CloseFucker();
void StopwatchDisplay();
void main()
{
EA = 1;
CloseFucker();
ConfigTimer0(1);
KEY_OUT_4 = 0;
while(1)
{
if(StopwatchRefresh)
{
StopwatchRefresh = 0;
StopwatchDisplay();
}
KeyDriver();
}
}
void CloseFucker()
{
P2 = (P2 & 0x1F) | 0xA0;
P0 = 0xAF;
P2 = 0x00;
}
void ConfigTimer0(u16 ms)
{
u32 tmp;
tmp = (11059200/12);
tmp = (tmp*ms)/1000;
tmp = 65536 - tmp;
T0RH = (u8)(tmp >> 8);
T0RL = (u8)tmp;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = T0RH;
TL0 = T0RL;
ET0 = 1;
TR0 = 1;
}
void StopwatchDisplay()
{
char i;
u8 buff[4];
LedBuff[0] = LedChar[DecimalPart%10];
LedBuff[1] = LedChar[DecimalPart/10];
buff[0] = IntegerPart % 10;
buff[1] = IntegerPart/10 % 10;
buff[2] = IntegerPart/100 % 10;
buff[3] = IntegerPart/1000 % 10;
for(i=3; i>0; i--)
{
if(buff[i] == 0x00)
{
LedBuff[i+2] = 0xFF;
}
else
{
break;
}
}
for( ; i>=0; i--)
{
LedBuff[i+2] = LedChar[buff[i]];
}
LedBuff[2] &= 0x7F;
}
void StopwatchReset()
{
StopwatchRunning = 0;
DecimalPart = 0;
IntegerPart = 0;
StopwatchRefresh = 1;
}
void StopwatchAction()
{
if(StopwatchRunning)
StopwatchRunning = 0;
else
StopwatchRunning = 1;
}
void KeyDriver()
{
static u8 backup[4] = { 1, 1, 1, 1};
u8 i;
for(i=0; i<4; i++)
{
if(KeySta[i] != backup[i])
{
if(backup[i] != 0)
{
if(i == 1)
{
StopwatchReset();
}
else if( i== 2)
{
StopwatchAction();
}
backup[i] = KeySta[i];
}
}
}
}
void LedScan()
{
static u8 index = 0;
P2 = (P2 & 0x1F) | 0xE0;
P0 = 0xFF;
P2 = 0x00;
P2 = (P2 & 0x1F) | 0xC0;
P0 = 0x80 >> index;
P2 = 0x00;
P2 = (P2 & 0x1F) | 0xE0;
P0 = LedBuff[index];
P2 = 0x00;
if(index < 7)
index++;
else
index=0;
}
void KeyScan()
{
u8 i;
static u8 keybuff[4] = {
0xFF, 0xFF, 0xFF, 0xFF
};
keybuff[0] = (keybuff[0] << 1) | KEY_IN_1;
keybuff[1] = (keybuff[1] << 1) | KEY_IN_2;
keybuff[2] = (keybuff[2] << 1) | KEY_IN_3;
keybuff[3] = (keybuff[3] << 1) | KEY_IN_4;
for (i=0; i<4; i++)
{
if((keybuff[i] & 0x0F) == 0x00)
KeySta[i] = 0;
else if((keybuff[i] & 0x0F) == 0x0F)
KeySta[i] = 1;
}
}
void StopwatchCount()
{
if(StopwatchRunning)
{
DecimalPart++;
if(DecimalPart == 100)
{
DecimalPart = 0;
IntegerPart++;
if(IntegerPart == 10000)
{
IntegerPart = 0;
}
}
StopwatchRefresh = 1;
}
}
void InterruptTimer0() interrupt 1
{
static u8 tmr10ms = 0;
TH0 = T0RH;
TL0 = T0RL;
LedScan();
KeyScan();
tmr10ms++;
if(tmr10ms == 10)
{
tmr10ms = 0;
StopwatchCount();
}
}
别忘了,backup[i] = KeySta[i]
更新backup的值,更别忘了它应该放置的正确位置。。