main.c
#include "reg52.h"
#include "ds1302.h"
#define ur unsigned char//
#define ut unsigned int
sfr AUXR=0x8e;//sfr特殊功能寄存器RAM(运行中保持不变再次烧写时改变)
sbit P30=P3^0;//ROM(在程序运行中随时改变)
sbit P31=P3^1;
sbit P32=P3^2;
sbit P33=P3^3;
bit modes;/*bit就是位,也叫比特位,是计算机表示数据最小的单位,例如 1b ,2b,3b.....
说白了就是0或者1*/
ur posd = 0;
ut timed = 0;
ur h,m,s,set = 1;
ur timer[3] = {0x50,0x59,0x23};
ur code ds1302_write[]={0x80,0x82,0x84};
ur code ds1302_read[]={0x81,0x83,0x85};
ur SMGNoDot_ca[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/*
code的作用是告诉单片机,我定义的数据要存储在ROM(程序存储区)里面,
写入后就不能再更改,其实是相当与汇编里面的寻址MOVC(好像是),
因为C语言中没办法详细描述存入的是ROM还是RAM(存储器),
所以在软件中添加了这一个语句起到代替汇编指令的作用,对应的还有data是存入RAM(存储器)的意思。
*/
void Config_DS1302 ();
void Initsystem();
void SMGdispaly(posd);
void HC138(ur channel,ur dat);
void Timer0Init(void);
void key_scan();
void LEDshow();
void Read_DS1302 ();
//==============主函数=====================
void main()
{
Config_DS1302 ();
Initsystem();
Timer0Init();
while(1)
{
if(timed%40==1)key_scan();
if(timed%100==11)LEDshow();
if(timed%400==21)Read_DS1302();
}
}
//=============================基础======================================================
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //时钟使能开关打开
EA = 1; //总使能开关打开
}
void Timer0()interrupt 1
{
posd == 7?posd = 0:posd++; //数码管位控制变量
timed == 1000?timed = 0:timed++;//周期计时变量
SMGdispaly(posd); //数码管显示
}
void Initsystem() //初始化LED,蜂鸣器,继电器
{
HC138(4,0xff);
HC138(5,0x00);
}
void HC138(ur channel,ur dat) //控制74HC138选择74Hc573锁存器
{
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80;P0=dat;break;
case 5:P2=(P2&0x1f)|0xa0;P0=dat;;break;
case 6:P2=(P2&0x1f)|0xc0;P0=dat;break;
case 7:P2=(P2&0x1f)|0xe0;P0=dat;break;
}
P2&=0x1f;
}
//============================ds1302======================================================
void Config_DS1302 () //初始化DS1302(写入)
{
ur i;
Write_Ds1302_Byte(0x8e,0x00);
for (i = 0;i<3;i++)
{
Write_Ds1302_Byte(ds1302_write[i],timer[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void Read_DS1302 () //读DS1302时钟
{
ur i;
EA=0; //使能总中断关闭
for (i = 0;i<3;i++)
{
timer[i] = Read_Ds1302_Byte(ds1302_read[i]);
}
EA=1; //使能总中断打开
}
//=================================数码管========================================================
void SMGbit(ur pos,ur dat)
{
HC138(7,0xff); //消隐(值)
HC138(6,0x01<<pos); //打开位
HC138(7,dat); //赋值
}
//显示界面
void SMGdispaly1(posd)
{
switch(posd)
{
case 0:SMGbit(posd,SMGNoDot_ca[timer[2]/16]);break;
case 1:SMGbit(posd,SMGNoDot_ca[timer[2]%16]);break;
case 2:SMGbit(posd,0xbf);break;
case 3:SMGbit(posd,SMGNoDot_ca[timer[1]/16]);break;
case 4:SMGbit(posd,SMGNoDot_ca[timer[1]%16]);break;
case 5:SMGbit(posd,0xbf);break;
case 6:SMGbit(posd,SMGNoDot_ca[timer[0]/16]);break;
case 7:SMGbit(posd,SMGNoDot_ca[timer[0]%16]);break;
}
}
//参数界面
void SMGdispaly2(posd)
{
ur c_t = 0,set_m = 0x89;
//设置显示值
switch(set)
{
case 1: set_m = 0x89; c_t = h;break;//set为1,模式为小时参数设置
case 2: set_m = 0xc8; c_t = m;break;
case 3: set_m = SMGNoDot_ca[5];c_t = s;break;
}
switch(posd)
{
case 0:SMGbit(posd,0xc6);break;
case 1:SMGbit(posd,set_m);break;
case 2:SMGbit(posd,0xff);break;
case 3:SMGbit(posd,0xff);break;
case 4:SMGbit(posd,0xff);break;
case 5:SMGbit(posd,0xbf);break;
case 6:SMGbit(posd,SMGNoDot_ca[c_t/10]);break;
case 7:SMGbit(posd,SMGNoDot_ca[c_t%10]);break;
}
}
//数码管显示(选择)
void SMGdispaly(posd)
{
if(!modes)SMGdispaly1(posd);
else SMGdispaly2(posd);
}
//=======================LED==========================================================
//参数1控制选择哪一位led灯,参数二控制亮灭。0为亮,1为灭
void led_show(ur pos,bit i)
{
static ur dat = 0xff;
if(i) dat |= 0x01<<pos;
else dat &= ~(0x01<<pos);
HC138(4,dat);
}
//led显示
void LEDshow()
{
static bit shan = 0;
EA = 0; //总使能开关关闭
if(modes)
{ //参数界面
led_show(0,1); //L1灭
led_show(1,0); //L2亮
switch(set)
{
case 1: //set为1,当前为小时参数设置
led_show(2,0); //L3亮
led_show(3,1); //L4灭
led_show(4,1); //L5灭
break;
case 2: //set为2,当前为分参数设置
led_show(2,1);
led_show(3,0);
led_show(4,1);
break;
case 3: //set为3,当前为秒参数设置
led_show(2,1);
led_show(3,1);
led_show(4,0);
break;
}
}
else//显示界面
{
//L1灭,L2,L3,L4,L5灭
led_show(0,0);
led_show(1,1);
led_show(2,1);
led_show(3,1);
led_show(4,1);
}
if(timer[2] == h*16 && timer[1] == m*16 && timer[0] == s*16) //当参数值等于实际值
shan = 1;
if(shan)
{
if(timed<500)
led_show(5,0);
else
led_show(5,1);
if(timer[0] >= s+5)
{
shan = 0;
led_show(5,0);//L6熄灭
}
}
EA = 1;
}
//=========================按键=================================================================
void key_scan()
{
static bit s4,s5,s6,s7; //1表示未按下(高电平)
//按键S7
if(P30) s7 = 1; //s7未按下 modes=0;
else if(s7) //s7按下 modes=1
{
modes ^= 1;//显示界面和参数界面切换
s7 = 0;
}
//按键S6
if(P31) s6 = 1;
else if(s6)
{
if(modes)
set == 3?set = 1:set++;//参数界面,时分秒界面切换-只有1和2两只状态
s6 = 0;
}
//按键S5
if(P32) s5 = 1;
else if(s5)
{
if(modes)//当处于参数界面
{
switch(set)
{
case 1: if(h!=23) h++;break;//时+1
case 2: if(m!= 59) m++;break;
case 3: if(s!=59) s++;break;
}
}
else led_show(5,1);//处于显示界面,L6熄灭
s5 = 0;
}
//按键S4
if(P33) s4 = 1;
else if(s4)
{
if(modes)//当处于参数界面
switch(set)
{ //是h为1否则为0
case 1: if(h) h--;break; //时-1
case 2: if(m) m--;break;
case 3: if(s) s--;break;
}
s4 = 0;
}
}
ds1302.h
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <reg52.h>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
#endif