下午闲的没事就拿出来放了两年的开发板,然后写了个小东西。童年梦想,电子表的程序。
程序实现了整点报时,每分钟LED闪烁一次,使用共阴数码管动态扫描实现时间日期的显示,通过两个按键可以调整时间。
实现的代码如下
#include <reg52.h>
/****************************************
*程序名称:时钟
*作者:独行
*时间:2017.2.23
*****************************************/
//定义数据端口
#define DataPort P0
//定义喇叭接口
sbit BEE = P2^0;
//定义LED端口
sbit LED = P2^7;
//定义按键
sbit KEY_CHANGE = P3^0;
sbit KEY_MOVE = P3^2;
//定义锁存使能端口
sbit SEGMENT_LATCH = P2^2;
sbit BIT_LATCH = P2^3;
//模式
/*
模式0:正常显示时间
模式1:正常显示日期
模式2:调整时间
模式3:调整日期
*/
unsigned char mode = 1, pos = 0;
//定义段码
unsigned char code segment_table[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
//定义位码
unsigned char code bit_table[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
//月份天数表
unsigned char code day_table[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//时间表
unsigned char time_table[8];
//日期表
unsigned char date_table[8];
//定义时间日期变量
unsigned char year, month, day, h, m, s;
//初始化定时器
void Init_Timer(void)
{
TMOD |= 0x01; //使用模式1
//初始化TH和TL即设置时间
TH0 = (0xffff-2000)/0xff;
TL0 = (0xffff-2000)%0xff;
EA = 1; //总中断开关
ET0 = 1; //定时器中断开关
TR0 = 1; //定时器0开关
}
//延时函数
void Delay(unsigned char i)
{
while (i--);
}
//延时函数单位毫秒
void DelayMs(unsigned int i)
{
while (i--){
Delay(245);
Delay(245);
}
}
//*************************增加数值函数区************************************
void AddYear()
{
unsigned char temp = 0;
if(!(++year%200)){//调整年,超过200年那么回来
year = 0;
}//year
//显示表重置
temp = year + 17;
date_table[1] = segment_table[temp/100];
date_table[2] = segment_table[temp/10];
date_table[3] = segment_table[temp%10];
}
void AddMonth()
{
unsigned char temp = 0;
if(!(++month%12)){//调整月,整年调整年
month = 0;
//如果不是暂停模式,那么继续增加年
if(!(0x80 & mode))AddYear();
}//month
temp = month + 1;
date_table[4] = segment_table[temp/10];
date_table[5] = segment_table[temp%10];
}
void AddDay()
{
unsigned char temp = 0;
//这里调整天数做了一个偷懒的工作,不去判断闰年的问题
if(!(++day%day_table[month])){//调整天,整月调整月
day = 0;
if(!(0x80 & mode))AddMonth();
}//day
temp = day +1;
date_table[6] = segment_table[temp/10];
date_table[7] = segment_table[temp%10];
}
void Addh()
{
if(!(++h)%24){//调整时,整天调整天
h = 0;
if(!(0x80 & mode))AddDay();
}//h
time_table[0] = segment_table[h/10];
time_table[1] = segment_table[h%10];
}
void Addm()
{
if(!(++m%60)){//调整分,整时调整时
m = 0;
if(!(0x80 & mode))Addh();
}//m
time_table[3] = segment_table[m/10];
time_table[4] = segment_table[m%10];
LED = 0;
Delay(200);
LED = 1;
}
void Adds()
{
if(!(++s%60)){//调整秒,整分调整分
s = 0;
if(!(0x80 & mode))Addm();
}//s
time_table[6] = segment_table[s/10];
time_table[7] = segment_table[s%10];
}
//*************************增加数值函数区结束************************************
int main()
{
year = month = day = h = m = s = 0;
//初始化时间表
time_table[0] = segment_table[0];
time_table[1] = segment_table[0];
time_table[2] = 0x40;
time_table[3] = segment_table[0];
time_table[4] = segment_table[0];
time_table[5] = 0x40;
time_table[6] = segment_table[0];
time_table[7] = segment_table[0];
//初始化日期表
date_table[0] = segment_table[2];
date_table[1] = segment_table[0];
date_table[2] = segment_table[1];
date_table[3] = segment_table[7];
date_table[4] = segment_table[0];
date_table[5] = segment_table[1];
date_table[6] = segment_table[0];
date_table[7] = segment_table[1];
Init_Timer();
//循环处理按键
while (1){
//整点报时功能
if(s < 10 && m == 0 && (0x01 & mode)){
BEE = ~BEE;
}
//按键判断
if(0 == KEY_CHANGE){
//如果改变的按键按下
DelayMs(10);//去抖
if(0 == KEY_CHANGE){
while (0 == KEY_CHANGE);
if(0x01 & mode){
//如果是正常显示模式,那么调整为调整时间模式
mode |= 0x04;
mode &= 0x84;
pos = 0x01;
}else if(!(0x80 & mode)){
mode |= 0x80;
}else if(0x04 & mode){
//调整当前位置的时间数值
if(0x01 & pos){
Addh();
//时+1
}else if(0x02 & pos){
Addm();
//分+1
}else if(0x04 & pos){
Adds();
//秒+1
}
}else if(0x08 & mode){
//调整当前位置的日期数值
if(0x40 & pos){
AddYear();
//年+1
}else if(0x20 & pos){
AddMonth();
//月+1
}else if(0x10 & pos){
AddDay();
//天+1;
}
}
}
}
if(0 == KEY_MOVE){
//移动键按下
DelayMs(10);//去抖
if(0 == KEY_MOVE){
while (0 == KEY_MOVE);//等待释放
if(0x01 & mode){//正常显示模式
mode = 0x02; //日期显示模式
DelayMs(300);//显示一会儿
mode = 0x01; //正常显示模式
}else if(0x04 & mode){
//调整时间模式
pos <<= 1;
if(0x08 & pos){
mode |= 0x08;
mode &= 0x88;
pos <<= 1;
}
}else if(0x08 & mode){
pos <<= 1;
if(0x80 & pos){
mode |= 0x01;
mode &= 0x81;
pos = 0;
}
}
}
}
}
return 0;
}
//时间日期显示函数
void DisPlay()
{
static unsigned int t = 0;
static unsigned char i = 0;
static char status = 0;
if(!(++t%500)){//一秒钟
t = 0;
status = ~status;
//如果是正常显示模式
if(!(0x80&mode)){
//那么调整时间
Adds();
}//t
}
DataPort = bit_table[i];
BIT_LATCH = 1;
BIT_LATCH = 0;
DataPort = time_table[i];
if(0x01 & mode){
//正常显示时间模式
DataPort = time_table[i];
}else if(0x02 & mode){
//正常显示日期模式
DataPort = date_table[i];
}else if(0x04 & mode){
//调整时间模式
if(0x04 & pos){//调整秒的模式
//闪烁
if((6 == i || 7 == i) && status){
DataPort = 0;
}else{
DataPort = time_table[i];
}
}else if(0x02 & pos){//调整分的模式
if((3 == i || 4 == i) && status){
DataPort = 0;
}else{
DataPort = time_table[i];
}
}else if(0x01 & pos){//调整时的模式
if((0 == i || 1 == i) && status){
DataPort = 0;
}else{
DataPort = time_table[i];
}
}
}else if(0x08 & mode){
//调整日期模式
if(0x40 & pos){//调整年的模式
//闪烁
if((0 == i || 1 == i || 2 == i || 3 == i) && status){
DataPort = 0;
}else{//如果不是上述模式,那么正常显示
DataPort = date_table[i];
}
}else if(0x20 & pos){//调整月的模式
if((4 == i || 5 == i) && status){
DataPort = 0;
}else{//如果不是上述模式,那么正常显示
DataPort = date_table[i];
}
}else if(0x10 & pos){//调整日的模式
if((6 == i || 7 == i) && status){
DataPort = 0;
}else{//如果不是上述模式,那么正常显示
DataPort = date_table[i];
}
}
}
i = ++i%8;
SEGMENT_LATCH = 1;
SEGMENT_LATCH = 0;
}
//定时器中断函数
void Timer0_isr(void) interrupt 1
{
//设置定时器的时间 2ms
TH0 = (0xffff-2000)/0xff;
TL0 = (0xffff-2000)%0xff;
DisPlay();
}
下面是变量pos和mod变量 每个方块是一个位。
真是时光荏苒!