基于STC89C52的DS1302应用
来源:互联网 发布:js属于什么语言 编辑:程序博客网 时间:2024/04/20 09:34
/*******************************基于DS1302时钟芯片万年历***************************/
/******************************************************************************
* Copyright (c) 2009,雲塘隱士東瓜电子工作室
* All rights reserved.
* 摘 要: 万年历:前两位显示分钟,后两位显示秒,
硬件连接:
1.P0口连接到4位数码管的数据端
2.四个数码管的位码口定义
小时: sbit P10 = P1^0;
sbit P11 = P1^1;
分钟: sbit P12 = P1^2;
sbit P13 = P1^3;
3.功能按键
模式选择键: sbit Mode = P2^0;
上调键: sbit UP = P2^1;
下调键: sbit DN = P2^2;
4.显示调节时按键指示
调时显示: sbit led1 = P2^3;
调分显示: sbit led2 = P2^4;
调闹钟时显示:sbit led3 = P2^5;
调闹钟分显示:sbit led4 = P2^6;
5.DS1302与MCU连接
DS1302时钟信号: sbit SCLK = P3^5; 7脚
DS1302数据信号: sbit DIO = P3^6; 6脚
DS1302片选: sbit CE = P3^7; 5脚
操作描述:按M键一次,进入修改小时模式,led1亮
按M键二次,进入修改分钟模式,led2亮
按M键三次,进入修改闹钟小时模式,led3亮
按M键四次,进入修改闹钟分钟模式,led4亮
按M键五次,退出修改模式
按UP或DN键可对小时或分钟进行修改(加或减)
程序要点:
* 文件名称: main.c
* CPU芯片: STC89C52RC
* 主频: 11.0592MHZ
*
* 当前版本: 1.0
* 作 者: 云塘东瓜
* 完成日期: 2009年6月1日
* 修改时间: 2009年6月4日
* 备注: 可以修改显示数据,可以显示年月日、周、时分秒
*******************************************************************************/
#include <reg52.h>
/********************************宏定义DS1302寄存器读写地址*************************/
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define WRITE_DAY 0x86
#define WRITE_MONTH 0x88
#define WRITE_WEEK 0x8A
#define WRITE_YEAR 0x8C
#define WRITE_TIMER_FLAG 0xC0
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define READ_DAY 0x87
#define READ_MONTH 0x89
#define READ_WEEK 0x8B
#define READ_YEAR 0x8D
#define READ_TIMER_FLAG 0xC1
#define WRITE_PROTECT 0x8E
/******************************************************************************/
/*********************************宏定义定时计数器初值******************************/
#define THCO 0xee //定时值5us
#define TLCO 0x00
/*****************************************************************************/
/*********************DS1302与MCU连接脚及驱动程序中用到的累加器定义*****************/
//位寻址寄存器定义
sbit ACC_7 = ACC^7;
//管脚定义
sbit SCLK = P3^5; // DS1302时钟信号 7脚
sbit DIO = P3^6; // DS1302数据信号 6脚
sbit CE = P3^7; // DS1302片选 5脚
/****************************************************************************/
/*******************************4位数码管段码、片选及时钟变量定义*******************/
//共阴极数码管,0-9段码表
unsigned char code Duan[]={0x3F, 0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//四个数码管显示数值,数组变量定义
unsigned char Data_Buffer[4]={0,0,0,0};
//秒分计时变量
unsigned char Sec = 40,Min=18,Hour=12,Day =1,Mon = 6,Week = 1,Year = 9;
//闹铃设置变量
unsigned char Set_Sec = 5,Set_Min = 20, Set_Hour = 12,Set_Day =1,Set_Mon = 6,Set_Week = 1,Set_Year = 9;
/********************************************************************************/
/**********************************标志位定义***************************************/
//设置掉电走时标志(timer_flag_rom初始化时写入rom下次与timer_flag比较)
unsigned char timer_flag = 0x14,timer_flag_rom = 0x20;
//模式切换标志
unsigned char flag_mode = 1;
//显示时钟标志,为1时显示走时或显示调节值(与flag结合)
bit flag_timer = 1;
//设置状态标志
bit Set_flag=0;
//动态扫描时间到标志/显示走时标志位,为1时显示
bit flag=1;
//走时设定标志
bit set_timer=1;
//开启走时标志
bit timer=1;
/****************************************************************************/
/*******************************led脚、数码管片选脚及功能设置脚定义*****************/
//四个数码管的位码口定义
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
//功能按键
sbit Mode = P2^0;
sbit UP = P2^1;
sbit DN = P2^2;
//led调节显示
sbit led1 = P2^3;
sbit led2 = P2^4;
sbit led3 = P2^5;
sbit led4 = P2^6;
//闹铃蜂鸣器
sbit P14 = P1^4;
/*******************************************************************************/
/**********************************十进制转换为十六进制子程序***************************/
/*****函数名称:unsigned char O_to_H(unsigned char n)
******功能: 十进制转换为十六进制
******参数传递:有,十进制数n
******返回值: 有,转换后的十六进制数
******创建时间:2009.6.1
******修改时间:
******/
/*******************************************************************************/
unsigned char O_to_H(unsigned char n)
{
unsigned char temp1;
temp1 = n/10*16 + n%10;
return(temp1);
}
/******************************************************************************/
/**********************************地址、数据发送子程序*****************************/
/*****函数名称:void Write1302 (unsigned char addr,dat)
******功能: 串行发送地址、数据,先发低位,且在上升沿发送
******参数传递:有,地址和数据
******返回值: 无
******创建时间:2009.6.1
******修改时间:
******/
/******************************************************************************/
void Write1302 (unsigned char addr,dat)
{
unsigned char i,temp;
CE=0; //CE引脚为低,数据传送中止
SCLK=0; //清零时钟总线
CE = 1; //CE引脚为高,逻辑控制有效
//发送地址
for ( i=8; i>0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr >>= 1; //右移一位
SCLK = 1;
}
//发送数据
for ( i=8; i>0; i-- )
{
SCLK = 0;
temp = dat;
DIO = (bit)(temp&0x01);
dat >>= 1;
SCLK = 1;
}
CE = 0;
}
/******************************************************************************/
/**********************************数据读取子程序*****************************/
/*****函数名称:unsigned char Read1302 ( unsigned char addr )
******功能: 串行读取数据,先发低位,且在下降沿发送
******参数传递:有,地址
******返回值: 有,读取的数据
******创建时间:2009.6.1
******修改时间:
******/
/*****************************************************************************/
unsigned char Read1302 ( unsigned char addr )
{
unsigned char i,temp,dat1,dat2;
CE=0;
SCLK=0;
CE = 1;
//发送地址
for ( i=8; i>0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr >>= 1; //右移一位
SCLK = 1;
}
//读取数据
for ( i=8; i>0; i-- )
{
ACC_7=DIO;
SCLK = 1;
ACC>>=1;
SCLK = 0;
}
CE=0;
dat1=ACC;
dat2=dat1/16; //数据进制转换
dat1=dat1%16; //十六进制转十进制
dat1=dat1+dat2*10;
return (dat1);
}
/*******************************************************************************/
/**********************************初始化DS1302子程序*****************************/
/*****函数名称:void Initial(void)
******功能: DS1302初始化,时分秒,年月日,周,和RAM(0xC0)
******参数传递:无
******返回值: 无
******创建时间:2009.6.1
******修改时间:
******/
/******************************************************************************/
void Initial(void)
{
Write1302 (WRITE_PROTECT,0x00); //禁止写保护
Write1302 (WRITE_SECOND,O_to_H(Sec)); //秒位初始化
Write1302 (WRITE_MINUTE,O_to_H(Min)); //分钟初始化
Write1302 (WRITE_HOUR,O_to_H(Hour)); //小时初始化
Write1302 (WRITE_DAY,O_to_H(Day)); //日初始化
Write1302 (WRITE_MONTH,O_to_H(Mon)); //月初始化
Write1302 (WRITE_WEEK,O_to_H(Week)); //周初始化
Write1302 (WRITE_YEAR,O_to_H(Year)); //年初始化
Write1302 ( WRITE_TIMER_FLAG,timer_flag_rom); //设置掉电走时标志
Write1302 (WRITE_PROTECT,0x80); //允许写保护
}
/**************************************************************/
/**********************************非走时初始化DS1302子程序************************/
/*****函数名称:void R_Initial(void)
******功能: DS1302初始化,时分秒,年月日,周,和RAM(0xC0)
******参数传递:无
******返回值: 无
******创建时间:2009.6.1
******修改时间:2009.6.4
******/
/***************************************************************************/
void R_Initial(void)
{
Write1302 (WRITE_PROTECT,0x00); //禁止写保护
Write1302 (WRITE_SECOND,0x80|O_to_H(Read1302(READ_SECOND))); //秒位初始化
Write1302 (WRITE_MINUTE,O_to_H(Min)); //分钟初始化
Write1302 (WRITE_HOUR,O_to_H(Hour)); //小时初始化
Write1302 (WRITE_DAY,O_to_H(Day)); //日初始化
Write1302 (WRITE_MONTH,O_to_H(Mon)); //月初始化
Write1302 (WRITE_WEEK,O_to_H(Week)); //周初始化
Write1302 (WRITE_YEAR,O_to_H(Year)); //年初始化
Write1302 ( WRITE_TIMER_FLAG,timer_flag_rom); //设置掉电走时标志
Write1302 (WRITE_PROTECT,0x80); //允许写保护
}
/*****************************************************************************/
/**************************************主程序**********************************/
/*****函数名称:void main(void)
******功能:
******参数传递:无
******返回值: 无
******创建时间:2009.6.1
******修改时间:
******/
/**************************************************************************/
void main(void)
{
//定时器0初始化
TMOD=0x10; //定时计数器1工作在方式1定时状态,5us,开中断
TH1=THCO;
TL1=TLCO;
TR1=1;
ET1=1;
EA=1;
//掉电依然走时,通过DS1302中读取中ram,与设定值比较,若相同则是掉电后重启,不需再次初始化
timer_flag = Read1302(READ_TIMER_FLAG);
if(timer_flag==(timer_flag_rom/16*10+timer_flag_rom%16))
{;}
else
Initial();
while(1)
{
if(flag==1&flag_timer==1)
{
flag = 0;
if(set_timer==1)
{
//显示走时
Data_Buffer[0] = Read1302(READ_MINUTE)/10;
Data_Buffer[1] = Read1302(READ_MINUTE)%10;
Data_Buffer[2] = Read1302(READ_SECOND)/10;
Data_Buffer[3] = Read1302(READ_SECOND)%10;
if(Set_Min == Read1302(READ_MINUTE))
P14 = 0;
else P14 = 1;
}
else
{
//显示调节时的值
Data_Buffer[0] = Min/10;
Data_Buffer[1] = Min%10;
Data_Buffer[2] = Sec/10;
Data_Buffer[3] = Sec%10;
}
}
if(Set_flag==1)
{
//显示设定闹钟值
Data_Buffer[0] = Set_Min/10;
Data_Buffer[1] = Set_Min%10;
Data_Buffer[2] = Set_Sec/10;
Data_Buffer[3] = Set_Sec%10;
}
}
}
/****************************************************************************/
/**********************************定时计数器1定时5us溢出中断**********************/
/*****函数名称:void timer1(void) interrupt 3
******功能:
******参数传递:无
******返回值: 无
******创建时间:2009.6.1
******修改时间:
******/
/***************************************************************************/
void timer1(void) interrupt 3
{
//静态变量,退出程序后,值保留
static unsigned char Bit=0; //标记数码管片选位
static unsigned char count1=0; //防抖程序计数标志
//再次装入计数初值
TH1=THCO;
TL1=TLCO;
//扫描显示控制部分
Bit++;
if(Bit>=4)Bit=0;
P1|=0x0f; //先关位码
P0=Duan[Data_Buffer[Bit]]; //开段码
switch(Bit) //送位码
{
case 0: P10=0;break;
case 1: P11=0;break;
case 2: P12=0;break;
case 3: P13=0;break;
}
//功能调节按键控制部分
if(Mode==0||UP==0||DN==0)
{
count1++;
if(count1>=30) //消抖处理
{
count1=0;
//读取分与秒的值
Min = Read1302(READ_MINUTE);
Sec = Read1302(READ_SECOND);
//显示时钟标志,清零不显示走时或调节
flag_timer = 0;
//开启走时标志,置1,进入调节状态,且不走时
timer=1;
if(timer==1)
{
if(Mode==0)
{
switch(flag_mode)
{
case 1: flag_mode = 2;
flag = 1;
flag_timer = 1;//显示时钟设置
Set_flag=0; //不显示闹钟
set_timer=0; //不显示走时
timer=1; //且不走时
led1 = 0;
break;
case 2: flag_mode = 3;
flag = 1;
flag_timer = 1;//显示时钟设置
Set_flag=0; //不显示闹钟
set_timer=0; //不显示走时
timer=1; //且不走时
led2 = 0;
break;
case 3: flag_mode = 4;
flag = 0; //不显示时钟设置
Set_flag=1; //显示闹钟
timer=1; //不走时
led3 = 0;
break;
case 4: flag_mode = 5;
flag = 0; //不显示时钟设置
Set_flag=1; //显示闹钟
timer=1; //不走时
led4 = 0;
break;
case 5: flag_mode = 1;
Set_flag=0; //不显示闹钟
flag_timer = 1;
flag = 1;
set_timer=1; //显示走时
timer=0; //不再是调节模式
Initial();
break;
default: break;
}
}
else if(DN==0) //下调
{
flag = 1;
flag_timer = 1;
Set_flag=0;
if(flag_mode==2)
{
flag = 1;
flag_timer = 1;
Set_flag=0;
if(Min>0)
Min--;
else Min = 59;
R_Initial();
//禁止走时
}
else if(flag_mode==3)
{
flag = 1;
flag_timer = 1;
Set_flag=0;
if(Sec>0)
Sec--;
else Sec = 59;
R_Initial();
//禁止走时
}
else if(flag_mode==4)
{
flag = 0;
Set_flag=1;
if(Set_Min>0)
Set_Min--;
else Set_Min = 59;
R_Initial();
//禁止走时
}
else if(flag_mode==5)
{
flag = 0;
Set_flag=1;
if(Set_Sec>0)
Set_Sec--;
else Set_Sec = 59;
R_Initial();
//禁止走时
}
}
else if(UP==0) //上调
{
flag = 1;
flag_timer = 1;
Set_flag=0;
if(flag_mode==2)
{
if(Min<59)
Min++;
else Min = 0;
R_Initial();
//禁止走时
}
else if(flag_mode==3)
{
flag = 1;
flag_timer = 1;
Set_flag=0;
if(Sec<59)
Sec++;
else Sec = 0;
R_Initial();
//禁止走时
}
else if(flag_mode==4)
{
flag = 0;
Set_flag=1;
if(Set_Min<59)
Set_Min++;
else Set_Min = 0;
R_Initial();
//禁止走时
}
else if(flag_mode==5)
{
flag = 0;
Set_flag=1;
if(Set_Sec<59)
Set_Sec++;
else Set_Sec = 0;
R_Initial();
//禁止走时
}
}
}
}
}
else flag=1;
}
/*****************************************************************************/
/**************************************end**********************************/
- 基于STC89C52的DS1302应用
- ds1302的应用问题
- 基于DS1302的万年历设计
- 基于stm32f103zet6的DS1302学习
- STC89C52单片机内部eeprom的应用
- 基于STM32的DS1302时钟芯片驱动
- 【51单片机学习笔记】基于STC89C52制作的交通信号灯
- STC89C52串口应用实例
- 实时时钟电路DS1302的原理及应用
- 我的STC89C52单片机
- 基于C语言STC89C52单片机电子密码锁的设计与仿真
- ds1302芯片的使用
- ds1302的一些认识
- DS1302基本的读写
- ds1302的使用
- 基于stc89c52蓝牙四轮小车
- 基于STC89C52单片机实现简易计算器
- STC89C52串口的复用
- Fixed Price and T&M contract
- Ubuntu9.04 Wubi安装的几点注意
- SQL删除表的方法
- 南方日报:不是我不用3G,是升级3G太复杂
- JRXlsExporter.setParameter常用参数说明
- 基于STC89C52的DS1302应用
- 65个源码网站
- throw throws 区别
- The Tao Of Programming —— 编程之道(小赵译版)
- 正式使用Flash Builder 4 Beta(含新功能介紹)
- 韩国设计网
- XEN虚拟机随系统启动
- 原型模式
- 60条绝对好用的生活常识