蓝桥杯 小蜜蜂 单元训练10:定时器实现秒表功能-数组方式
/*
* @Description:
* @Author: fdzhang
* @Email: zfdc@qq.com
* @Date: 2024-08-15 21:58:53
* @LastEditTime: 2024-08-16 19:07:27
* @LastEditors: fdzhang
*/
#include "stc15f2k60s2.h"
#define LED(x) \
{ \
P2 = P2 & 0x1f | 0x80; \
P0 = x; \
P2 &= 0x1f; \
}
// y7c 111,0xE0
#define SEG(x) \
{ \
P0 = x; \
P2 = P2 & 0x1f | 0xE0; \
P2 &= 0x1f; \
}
// y6c 110,0xC0
#define COM(x) \
{ \
P0 = x; \
P2 = P2 & 0x1f | 0xC0; \
P2 &= 0x1f; \
}
typedef unsigned char uint8_t;
uint8_t *setStopWatch(uint8_t min10, uint8_t min1, uint8_t sec10, uint8_t sec1, uint8_t ms10, uint8_t ms1)
{
uint8_t *stopWatchTimer[6];
*stopWatchTimer[0] = min10;
*stopWatchTimer[1] = min1;
*stopWatchTimer[2] = sec10;
*stopWatchTimer[3] = sec1;
*stopWatchTimer[4] = ms10;
*stopWatchTimer[5] = ms1;
return stopWatchTimer;
}
uint8_t com1 = 0x01; // 定义数码管的8个口
uint8_t com2 = 0x02;
uint8_t com3 = 0x04;
uint8_t com4 = 0x08;
uint8_t com5 = 0x10;
uint8_t com6 = 0x20;
uint8_t com7 = 0x40;
uint8_t com8 = 0x80;
sbit s4 = P3 ^ 3; // 定义按键
sbit s5 = P3 ^ 2;
code unsigned char Seg_Table[] =
{
0xc0, // 0
0xf9, // 1
0xa4, // 2
0xb0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xf8, // 7
0x80, // 8
0x90, // 9
0xBF // 符号"-"
};
uint8_t timerCounter = 0;
uint8_t counter50ms = 0;
uint8_t counter1s = 0;
uint8_t counter1min = 0;
uint8_t counter1h = 0;
void Timer0_Init(void) // 5毫秒@12MHz
{
AUXR |= 0x80; // 定时器时钟1T模式
TMOD &= 0xF0; // 设置定时器模式
TL0 = 0xA0; // 设置定时初始值
TH0 = 0x15; // 设置定时初始值
TF0 = 0; // 清除TF0标志
// TR0 = 1; // 定时器0开始计时 //因为题目要求可以暂停,所以一开始不要打开
ET0 = 1; // 使能定时器0中断
EA = 1;
}
// 使用STC - ISP中的延时计算器生成,
// 不想再使用定时器1生成时间间隔了,有些麻烦。
// 注意,延时500us会有重影
void Delay1ms() //@12.000MHz 使用STC-ISP中的延时计算器生成
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j)
;
} while (--i);
}
void oneSegShow(uint8_t comX, uint8_t showNum) // 单数码管显示
{
COM(comX);
SEG(Seg_Table[showNum]);
}
void min10Seg1(uint8_t min10) // 1管显示分10位
{
oneSegShow(com1, min10);
}
void min1Seg2(uint8_t min1) // 2管显示分个位
{
oneSegShow(com2, min1);
}
void dashSeg3() // 3管显示符号-
{
oneSegShow(com3, 10);
}
void sec10Seg4(uint8_t sec10) // 4管显示秒10位
{
oneSegShow(com4, sec10);
}
void sec1Seg5(uint8_t sec1) // 5管显示秒个位
{
oneSegShow(com5, sec1);
}
void dashSeg6() // 6管显示符号-
{
oneSegShow(com6, 10);
}
void ms10Seg7(uint8_t ms10) // 7管显示毫秒10位
{
oneSegShow(com7, ms10);
}
void ms1Seg8(uint8_t ms1) // 8管显示毫秒个位
{
oneSegShow(com8, ms1);
}
uint8_t arrayStatus; // 状态机显示方式
void segsAllShowFSM(uint8_t *stopWatchTimer) // Finite state machine
{
switch (arrayStatus)
{
case 0:
min10Seg1(stopWatchTimer[0]);
Delay1ms();
arrayStatus = 1;
break;
case 1:
min1Seg2(stopWatchTimer[1]);
Delay1ms();
arrayStatus = 2;
break;
case 2:
dashSeg3();
Delay1ms();
arrayStatus = 3;
break;
case 3:
sec10Seg4(stopWatchTimer[3]);
Delay1ms();
arrayStatus = 4;
break;
case 4:
sec1Seg5(stopWatchTimer[4]);
Delay1ms();
arrayStatus = 5;
break;
case 5:
dashSeg6();
Delay1ms();
arrayStatus = 6;
break;
case 6:
ms10Seg7(stopWatchTimer[5]);
Delay1ms();
arrayStatus = 7;
break;
case 7:
ms1Seg8(stopWatchTimer[6]);
Delay1ms();
arrayStatus = 0;
break;
default:
arrayStatus = 0;
break;
}
}
uint8_t s4Status;
uint8_t falling;
uint8_t counterOnOff = 0;
uint8_t keyStatus;
uint8_t keyValue;
void readKey()
{
switch (keyStatus)
{
case 0:
if ((s4 == 0) | (s5 == 0))
{
keyStatus = 1;
falling = 1;
keyStatus = 1;
}
break;
case 1:
if (s5 == 0)
{
keyValue = 5;
}
else if (s4 == 0)
{
keyValue = 4;
}
if (falling)
{
counterOnOff = ~counterOnOff;
}
if ((s4 == 0) | (s5 == 0)) // 如果长按锁定在当前状态
{
falling = 0;
keyStatus = 1;
}
else
keyStatus = 2;
break;
case 2:
if ((s4 == 1) && (s5 == 1))
keyStatus = 0;
default:
keyStatus = 0;
break;
}
}
void keyScan()
{
uint8_t *arrayTimer;
uint8_t ms10;
uint8_t ms1;
uint8_t sec10;
uint8_t sec1;
uint8_t min10;
uint8_t min1;
readKey();
if (keyValue == 5)
{
timerCounter = 0; // 清零
counter50ms = 0;
counter1s = 0;
counter1min = 0;
counter1h = 0;
ms10 = counter50ms / 10;
ms1 = counter50ms % 10;
sec10 = counter1s / 10;
sec1 = counter1s % 10;
min10 = counter1min / 10;
min1 = counter1min % 10;
arrayTimer = setStopWatch(min10, min1, sec10, sec1, ms10, ms1);
segsAllShowFSM(arrayTimer);
}
else if (keyValue == 4)
{
ms10 = counter50ms / 10;
ms1 = counter50ms % 10;
sec10 = counter1s / 10;
sec1 = counter1s % 10;
min10 = counter1min / 10;
min1 = counter1min % 10;
arrayTimer = setStopWatch(min10, min1, sec10, sec1, ms10, ms1);
segsAllShowFSM(arrayTimer);
if (counterOnOff)
{
TR0 = 1; // open timer启动恢复
}
else
{
TR0 = 0; // pause timer//暂停
}
}
}
void main()
{
LED(0xff); // 关闭LED
COM(0xFF); // 关闭数码管
// SEG(Seg_Table[0]);
Timer0_Init();
while (1)
{
keyScan();
}
}
void Timer0_Isr(void) interrupt 1
{
if (++timerCounter == 10) // 5毫秒为基本单位,50ms为一个计时单元
{
timerCounter = 0;
if (++counter50ms == 20) // 1s
{
counter50ms = 0; // 数码管显示的毫秒的数值
if (++counter1s == 60) // 1min
{
counter1s = 0; // 数码管显示的秒的数值
if (++counter1min == 60) // 1h
{
counter1min = 0; // 数码管显示的分的数值
}
}
}
}
}