AL第二次任务实现代码

概述

完成目标

任务书+闹钟(串口通信要用的T1被占了,没做(故意的还是不小心的))

编写的思路

尝试性的把数码管的扫描输出放进了定时器,这样就不用到处写显示函数了。
不同模式有不同的循环函数。
通过tmp_time[]表示定时时间。

应该改进的

编写思路太倾向于大循环里套小循环。
其实可以单一循环,然后根据多个flag来执行需要执行的操作。
矩阵键盘的扫描里有个空的while会卡CPU,解决方法是上次开会讲的根据上升下降沿,太久过去忘了应用(被打)
最好还是不要让定时器来干比较复杂的事情,耗时太久会进入一个闭环。

关键代码

(Nixie.c中修改索引10显示为‘-’)

DS1302_mine.h

#ifndef __DS1302_MINE_H__
#define __DS1302_MINE_H__
	extern char time[];
	void DS1302_Init(void);
	void DS1302_wr(char cmd,char Data);
	char DS1302_re(char cmd);
	void DS1302_wr_time(void);
	void DS1302_re_time(void);
	
#endif

DS1302_mine.c

	#include <REGX52.H>

#define p_s	0x80
#define p_m	0x82
#define p_h	0x84

sbit SCLK1=P3^6;
sbit IO1=P3^4;
sbit CE1=P3^5;

char time[3]={12,0,0};
char to_BCD(char num)
{
	return num%10+num/10*16;
}
char to_num(char bcd)
{
	return bcd%16+bcd/16*10;
}

void DS1302_wr(char cmd,char Data)//写入函数
{
	unsigned char i;
	CE1=1;
	for(i=0;i<8;i++)
	{
		SCLK1=0;
		IO1=cmd&(0x01<<i);
		SCLK1=1;
	}
	for(i=0;i<8;i++)
	{
		SCLK1=0;
		IO1=Data&(0x01<<i);
		SCLK1=1;
	}
	CE1=0;
}
char DS1302_re(char cmd)//读取函数
{
	char i,Data=0x00;
	CE1=1;
	cmd |= 0x01;
	for(i=0;i<8;i++)
	{
	
		IO1=cmd&(0x01<<i);
		SCLK1=0;
		SCLK1=1;
	}
	for(i=0;i<8;i++)
	{
		SCLK1=1;
		SCLK1=0;
		if(IO1){Data|=(0x01<<i);}
	}
	CE1=0;
	IO1=0;

	return Data;
}
void DS1302_wr_time(void){ 	//time[]全部写入
	DS1302_wr(p_h,to_BCD(time[0]));
	DS1302_wr(p_m,to_BCD(time[1]));
	DS1302_wr(p_s,to_BCD(time[2]));
}
void DS1302_re_time(void){	//读取芯片数据到time[]
	time[0]=to_num(DS1302_re(p_h));
	time[1]=to_num(DS1302_re(p_m));
	time[2]=to_num(DS1302_re(p_s));
}
void DS1302_Init(void) //初始化
{
	SCLK1=0;
	CE1=0;
	DS1302_wr(0x8E,0x00);//使得可以写入
}

main.c

#include <REGX52.H>
#include <INTRINS.h> 

#include "nixie.h"
#include "MatrixKey.h"
#include "DS1302_mine.h"
#include "Delay.h"

char shining=1;//闪烁标记位
char flag_s_ctrl=0,flag_setting=0,flag_boom=0;
//时分秒哪个闪烁;是否在设定闹钟(切换到显示tmp_time[]);是否到钟
char key=0;//表示按下的按键
char tmp_time[3]={0,0,0};//设定的闹钟时间                       
unsigned char code Animation[]={
	0x78,0x84,0x82,0x41,0x41,0x82,0x84,0x78,
	0x00,0x38,0x44,0x22,0x22,0x44,0x38,0x00,
};//忘记删了,尝试用点阵屏,但是没有

void show_time(char h,char m,char s)//集成的显示函数
{
	//根据shining和flag_s_ctrl确定是否点亮那个部分
	if (shining==0)	{Nixie(3,10);Nixie(6,10);}
	if (shining==1||flag_s_ctrl!=1){Nixie(1,h/10%10);Nixie(2,h%10);}
	if (shining==1||flag_s_ctrl!=2){Nixie(4,m/10%10);Nixie(5,m%10);}
	if (shining==1||flag_s_ctrl!=3){Nixie(7,s/10%10);Nixie(8,s%10);}
}
	
void Timer0_Init(void)		//1毫秒@11.0592MHz 半秒计时
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;
	EA=1;
	IP=0x02;      //保证计时的高优先级
	
}
void Timer1_Init(void)		//20毫秒@11.0592MHz,用来刷新显示函数
{
	TMOD &= 0x0F;			//设置定时器模式
	TMOD |= 0x10;			//设置定时器模式
	TL1 = 0x00;				//设置定时初始值
	TH1 = 0xB8;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	ET1=1;
	
}
/*以下为各个函数的模式*/
void show_mode()//显示模式
{
	while(key!=4&&key!=12)
	{
		key=MatrixKey();
		DS1302_re_time();
		if(time[0]==tmp_time[0] && time[1]==tmp_time[1] && time[2]==tmp_time[2])//判断时间到没到
		{
			flag_boom=1;
			while(key!=8){
				key=MatrixKey();
			}
			flag_boom=0;
		}
	}
}

void adjust_mode()//调整模式
{
	while(key!=8&&key!=12)
	{
		key=MatrixKey();
		if(key==1){flag_s_ctrl=1;time[0]=(time[0]+1)%24;}
		if(key==5){flag_s_ctrl=1;time[0]=(time[0]-1+24)%24;}
		if(key==2){flag_s_ctrl=2;time[1]=(time[1]+1)%60;}
		if(key==6){flag_s_ctrl=2;time[1]=(time[1]-1+60)%60;}
		if(key==3){flag_s_ctrl=3;time[2]=(time[2]+1)%60;}
		if(key==7){flag_s_ctrl=3;time[2]=(time[2]-1+60)%60;}
	}
	flag_s_ctrl=0;//所有数字停止闪烁
	DS1302_wr_time();//讲设定的值写入芯片中
}

void setting_mode()//设定闹钟模式
{
	flag_setting=1;//切换显示为tmp_time[]
	while(key!=8&&key!=4)
	{
		key=MatrixKey();
		if(key==1){flag_s_ctrl=1;tmp_time[0]=(tmp_time[0]+1)%24;}
		if(key==5){flag_s_ctrl=1;tmp_time[0]=(tmp_time[0]-1+24)%24;}
		if(key==2){flag_s_ctrl=2;tmp_time[1]=(tmp_time[1]+1)%60;}
		if(key==6){flag_s_ctrl=2;tmp_time[1]=(tmp_time[1]-1+60)%60;}
		if(key==3){flag_s_ctrl=3;tmp_time[2]=(tmp_time[2]+1)%60;}
		if(key==7){flag_s_ctrl=3;tmp_time[2]=(tmp_time[2]-1+60)%60;}
	}
	flag_s_ctrl=0;
	flag_setting=0;//退出tmp_time[]的显示
}
void main()  //主函数
{
	Timer0_Init();
	Timer1_Init();
	DS1302_Init();
	while(1)
	{
		DS1302_wr_time();//初始化为12-00-00,等待模式的选择
		key=MatrixKey();
		if(key==8||key==4||key==12){
			while(1)
			{
				if(key==12) //进入对应具体的模式,函数结束全局的key肯定会有一个新的值,
				{setting_mode();}//就不用再读取新的key了,不然会使得key=0然后程序停留在左侧这个循环中
				if(key==8)
				{show_mode();}
				if(key==4)
				{adjust_mode();}
			}
		}
	}
}


void shining_ctrl() interrupt 1
{
	static unsigned int T0Count;
    TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	T0Count++;
	if(T0Count>=500)
	{
		T0Count=0;
		shining=1-shining;
	}
}
void kee_show() interrupt 3
{
	char i;
	TL1 = 0x00;				//设置定时初始值
	TH1 = 0xB8;				//设置定时初始值
	if(flag_boom==0){		
		if(flag_setting)	//显示的切换
		{
			show_time(tmp_time[0],tmp_time[1],tmp_time[2]);
		}else{
			show_time(time[0],time[1],time[2]);
		}
	}else{ //我去,闹钟怎么响了
		for(i=1;i<80;i++){
			if (shining==0){Nixie(i/10,10);}
		}//很莫名其妙,不懂事写着玩的是
	}                                                                                                                                                                                                                                                                                
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值