利用单片机DS1302芯片编制数字时钟程序:能计算2100之前的秒,分,时,日,星期,月和年的能力,能进行闰

利用单片机DS1302芯片编制数字时钟程序:能计算2100之前的秒,分,时,日,星期,月和年的能力,能进行闰,第1张

/*******************************************************************************

文件:DS1302.C

环境:编余哪译为ICC AVR6.25A,仿真为AVR Studio4.10

硬件:ATMEGA64L芯片

日期:2008年3月7日

功能:驱动时钟芯片DS1302

备注:

*******************************************************************************/

/*=======================硬件说明迅敏===============================================

指令 指令码 功能

==============================================================================*/

//=======================头文件=================================================

#include <iom64v.h>

#include <macros.h>

#include <signal.h>

#include <stdio.h>

#include <math.h>

#include <string.h>

#include "main.h"

#include "Variable.h"

#include "DS1302.h"

//==============================================================================

/****************************************************************

* 名称 : void Reset_3wire(void)

* 功能描述: reset and enable the 3-wire interfaT_CE

* 输入参量: 无

* 输出参量: 无

* 调用子程: 无

* 使用方法: 对3-wire *** 作的话,首先要使能

-------------------------------------------------*/

void Reset_3wire(void)

{

DS1302_RST_OUT// 输出

DS1302_CLK_OUT

DS1302_IO_OUT

DS1302_CLK_LOW

Delay_nus(10)

DS1302_RST_LOW

Delay_nus(10)

DS1302_RST_HIGH

Delay_nus(10)

}

/****************************************************************

* 名称 : void Write_Byte_3W(unsigned char W_Byte)

* 功能描述: write one byte to the deviT_CE

* 输入参量: 需要写的字竖昌码节

* 输出参量: 无

* 调用子程: 无

* 使用方法: 无论读写,都首先要写东西

-------------------------------------------------*/

void Write_Byte_3W(unsigned char W_Byte)

{

unsigned char i

for(i = 0i <8i++)

{

DS1302_IO_LOW

if(W_Byte &0x01)

{

DS1302_IO_HIGH /* set port pin high to read data */

}

Delay_nus(10)

DS1302_CLK_LOW

Delay_nus(10)

DS1302_CLK_HIGH

Delay_nus(10)

W_Byte >>= 1

}

}

//****************************************************************

/****************************************************************

* 名称 : unsigned char Read_Byte_3W()

* 功能描述: read one byte from the deviT_CE

* 输入参量: 需要写的字节

* 输出参量: 读出的数据

* 调用子程: 无

* 使用方法: 从3 线器件读数据

----------------------------*/

unsigned char Read_Byte_3W(void)

{

unsigned char i

unsigned char R_Byte

unsigned char TmpByte

R_Byte = 0x00

DS1302_IO_IN //0xF7//改变io 口的方向为输入

Delay_nus(10)

for(i = 0i <8i++)

{

DS1302_CLK_HIGH

Delay_nus(10)

DS1302_CLK_LOW //下降沿数据有效

Delay_nus(10)

if(READ_DS1302_IO)

TmpByte=1//位 *** 作要小心

else

TmpByte=0

TmpByte <<= 7

R_Byte >>= 1

R_Byte |= TmpByte

}

return R_Byte

}

//******************************************************************

/****************************************************************

* 名称 : Get_Time

* 功能描述: 读取DS1302 当前时间

* 输入参量: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年

7Byte (BCD 码) 1B 1B 1B 1B 1B 1B 1B

* 输出参量: 无

* 调用子程: 无

* 使用方法:

----------------------------*/

void DS1302_Get_Time(unsigned char ucCurtime[])

{

unsigned char i

Reset_3wire()

Write_Byte_3W(0xBF)/* clock burst */

for(i=0i<7i++)

ucCurtime[i]=Read_Byte_3W()

//Reset_3wire()

DS1302_RST_LOW

}

/****************************************************************

* 名称 : Set_Time

* 功能描述: initialize time &date from user entries

* 输入参量: unsigned char yr, mn, date, dy, hr, min, sec, day设置时间并启动

* 输出参量: OK--- 设置成功

* ERROR --- 时间格式错误,无法设置

* 调用子程: 无

* 使用方法:

----------------------------*/

unsigned char DS1302_Set_Time(unsigned char *pClock)

{

unsigned char i

i = Check_Time(pClock)

if(i == ERROR)

return ERROR

pClock[5] = Get_Day(pClock[6],pClock[4],pClock[3])//取星期

//hr = hr &0x3f/* forT_CE clock to 24 hour mode */

Reset_3wire()

Write_Byte_3W(0x8e)/* control register */

Write_Byte_3W(0)/* disable write protect */

Reset_3wire()

//Write_Byte_3W(0x90)/* trickle charger register */

//Write_Byte_3W(0xab)/* enable, 2 dT IOdes, 8K resistor */

//Reset_3wire()

Write_Byte_3W(0xbe)/* clock burst write (eight registers) */

for(i=0i<7i++)

{

Write_Byte_3W(*(pClock++))

}

Write_Byte_3W(0)/* must write control register in burst mode */

//Reset_3wire()

DS1302_RST_LOW

return OK

}//******************************************************************

//------------------------------------------------------------------------------

//函数名称:Get_Day

//函数功能:根据年月日算出星期

//函数参数:year --- 年

// month --- 月

// date --- 日

//函数返回:day --- 星期

//------------------------------------------------------------------------------

//计算公式使用著名的蔡勒(Zeller)公式。即:

//w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

//公式中的符号含义如下,

//w:星期;

//c:世纪-1;

//y:年(两位数);

//m:月(m大于等于3,小于等于14,即在蔡勒公式中,

// 某年的1、2月要看作上一年的 13、14月来计算,

// 比如2003年1月1日要看作2002年的13月1日来计算);

//d:日;[ ]代表取整,即只要整数部分。

//C是世纪数减一,y是年份后两位,M是月份,d是日数。

//1月和2月要按上一年的13月和 14月来算,这时C和y均按上一 年取值。

//------------------------------------------------------------------------------

unsigned char Get_Day(unsigned char year,unsigned char month,unsigned char date)

{

unsigned char day

unsigned int temp

unsigned char century

year = Hex_To_Decimal(year)

month = Hex_To_Decimal(month)

date = Hex_To_Decimal(date)

century = 20

if(month <3)

{

month += 12

if(year == 0)

{

year = 99

century --

}

else

year --

}

temp = (month + 1) * 26

temp = temp / 10

temp += year

temp += (year >>2)

temp += (century >>2)

temp -= (century <<1)

temp += date

temp --

day = temp % 7

if(day == 0)

day = 7

return day

}

//=======================函数===============================================

//函数名称:Check_Time

//函数功能:检查时间格式是否正确,只能检查2000-2099年

//函数参数:buffer --- 时间:字节从高到低,年 星期 月 日 时 分 秒

//函数返回:result --- OK: 格式正确

// ERROR:格式错误

//==============================================================================

unsigned char Check_Time(unsigned char *buffer)

{

unsigned char year

unsigned char month

unsigned char date

unsigned char hour

unsigned char minute

unsigned char second

year = Hex_To_Decimal(buffer[6])

month = Hex_To_Decimal(buffer[4])

date = Hex_To_Decimal(buffer[3])

hour = Hex_To_Decimal(buffer[2])

minute = Hex_To_Decimal(buffer[1])

second = Hex_To_Decimal(buffer[0])

if(second >= 60)

buffer[0] = 0x30

if(minute >= 60)

return ERROR

if(hour >= 24)

return ERROR

if(month >= 13)

return ERROR

if(month &1)

{

if(date >= 32)

return ERROR

}

else if(month == 2)

{

if(year % 4)

{

if(date >= 29)

return ERROR

}

else

{

if(date >= 30)

return ERROR

}

}

else

{

if(date >= 31)

return ERROR

}

return OK

}

一、AVR系列单片机开发板

本开发板可使用于多种型号的AVR单片机,本板主配ATmega16单片机。除了丰富的硬件资源外,还配有仿真器,可以很方便的调试硬件,大大减小调试周期。所有IO口全部引出,用户可以任意扩展功能。

二、AVR_PQ1A开发桐蠢板实例程序(演示程序)

( 1 ) LED LED灯驱动程序,两种演示方式

( 2 ) SMG 数码管驱动程序,循环滚动显示数字1-6

( 3 ) 1602 1602液晶驱动程序,除正常显示ASCII码外,还教如何显示中文

( 4 ) 12864 12864液晶驱动程序,显示汉字和图形。液晶为带字库的 ST7920控制器的液晶。

( 5 ) SKEY 4个独立按键驱动程序,采用查询方式驱动

( 6 ) SKEY_INT 利用按键产生外部中断,教你中断程序的编写

( 7 ) MKEY 4x4矩阵按键驱动程序,教你如何扫描矩阵按键

( 8 ) TIMER0INT 定时器0驱动程序,教你如何使用定时器

( 9 ) AD Mega16自带的AD的驱动程局神陪序

( 10 ) DA SPI接口的8位DA驱动程序,利用Mega16的硬SPI接口

( 11 ) DS18B20 数字温度传感器驱动程序,教你如何显示小数

( 12 ) TWI( IIC ) IIC接口数字电位器驱动程序,利用Mega16的硬件IIC接口

( 13 ) BEEP 蜂鸣器唱歌程序,教你如何唱出好听的歌曲

( 14 ) PWM Mega16的定时器1驱动程序,实现PWM输出功能

( 15 ) RELAY 继电器驱动程序,利用Mega16的I/O口直接驱瞎腊动继电器

( 16 ) UART Mega16的异步串口驱动程序,教你如何实现串口通信

( 17 ) RTC 时钟芯片驱动程序,可以显示和利用按键设定时间

( 18 ) EEPROM Mega16的EEPROM驱动程序,读写内部EEPROM

( 19 ) PS2 标准PS2键盘驱动程序,教你如何读入扫描码并译成ASCII码

( 20 ) USB USBD12固件程序,教你实现枚举过程和数据传输

( 21 )uC/OS-II 移植好的 *** 作系统,执行两个任务,编译后,占用Mega16的26%资源。

/***时钟芯片DS1302驱动——火柴天堂作品-20120610***/

/***源程序硬件环境:52单片机,12MHz晶振,P34接时钟芯片IO脚,P35接芯片RST/CE脚,P36接芯片CLK脚***/

/******/

#define DS1302_H

#include"reg52.h" //包含52头文件

#include"DS1302.h" //包含DS1302宏定义文件

sbit DS1302_CLK=P3^6 //定义 CLK 接口

sbit DS1302_IO=P3^4 //定义 IO 接口

sbit DS1302_nRST=P3^5 //定义 RST 接口

#define RST_En DS1302_nRST=1 //使能

#define RST_Dis DS1302_nRST=0 //禁止

void DS1302_Init() //SD1302端口初始化函数

{

RST_Dis //禁止 *** 作扒蠢穗

DS1302_CLK=0 //时钟接口置 低常态

DS1302_IO=1 //数据接口置 高常态

}

uchar DS1302_ReadByte(uchar read_addr) //SD1302读函数,形参为 读地址

{

uchar i,read_data=0

RST_Dis //禁止 *** 作

DS1302_CLK=0 //时钟接口置 低常态

RST_En //允许 *** 作

for(i=0i<8i++) //输入8位地址

{

DS1302_CLK=0

if(read_addr &(1<<i)) DS1302_IO=1 //转换地址相应位,并输出至数据接口

else DS1302_IO=0 //转换地址相应位,并输出至数据接口

DS1302_CLK=1 //上升沿数据被DS1302接收

}

for(i=0i<8i++) //输出8位数据

{

DS1302_CLK=0 //下降沿,数据从DS1302输出

if(DS1302_IO) read_data|=1<<i //读取数据,并送往数据寄存器相应位

DS1302_CLK=1

}

RST_Dis //禁止 *** 作

DS1302_CLK=0 //时钟接口置 低常态

return read_data //返回读取数据

}

void DS1302_ReadDate(uchar *buf_p,uchar store_start) //DS1302读时间函数,返回十进制格式"年月日周时分春卜秒",共占7个uchar空间

{

buf_p+=store_start

*buf_p=DS1302_ReadByte(Read_Year) //年

*buf_p=(*buf_p>>4)*10+(*buf_p &0x0f) //BCD转Hex

*++buf_p=DS1302_ReadByte(Read_Month) //月

*buf_p=(*buf_p>>4 &0x01)*10+(*buf_p &0x0f) //BCD转Hex

*++buf_p=DS1302_ReadByte(Read_Day) //日

*buf_p=(*buf_p>>4 &0x03)*10+(*buf_p &0x0f) //BCD转Hex

*++buf_p=DS1302_ReadByte(Read_Week) //周

*buf_p&=0x07 //BCD转Hex

//*buf_p%=7 //0-6格式表示周

*++buf_p=DS1302_ReadByte(Read_Hour) //时

*buf_p=(*buf_p>>4 &0x03)*10+(*buf_p &0x0f) //BCD转Hex

*++buf_p=DS1302_ReadByte(Read_Min) //分

*buf_p=(*buf_p>>4 &0x07)*10+(*buf_p &0x0f) //BCD转Hex

*++buf_p=DS1302_ReadByte(Read_Sec) //秒

*buf_p=(*buf_p>>4 &0x07)*10+(*buf_p &0x0f) //BCD转Hex

}

//void DS1302_WriteByte(uchar write_com,uchar write_data) //DS132写函数,形参write_com为 *** 作指令,write_data为 *** 作数据

//{

// uchar i

// RST_Dis //禁止 *** 作

// DS1302_CLK=0 //时钟接口置 低常态档闷

// RST_En //允许 *** 作

// for(i=0i<8i++) //输入8位地址

// {

// if(write_com &1<<i) DS1302_IO=1 //转换指令相应位,并输出至数据接口

// else DS1302_IO=0 //转换指令相应位,并输出至数据接口

// DS1302_CLK=1 //上升沿数据被DS1302接收

// DS1302_CLK=0

// }

// for(i=0i<8i++) //输入8位地址

// {

// if(write_data &(1<<i)) DS1302_IO=1 //转换数据相应位,并输出至数据接口

// else DS1302_IO=0 //转换指令相应位,并输出至数据接口

// DS1302_CLK=1 //上升沿数据被DS1302接收

// DS1302_CLK=0

// }

// RST_Dis //禁止 *** 作

//}

//void DS1302_TimesInit(uint year,uchar month,uchar day,uchar week,uchar hour,uchar min,uchar sec,uchar hour_mode,uchar clock_state) //时间初始化函数

//{

// if(hour_mode!=H12_Mode &&hour_mode!=H24_Mode) hour_mode=H24_Mode //默认24小时制模式

// if(clock_state!=ClockHalt &&clock_state!=ClockStart) clock_state=ClockStart //默认时钟启动状态

// year%=100 //百年历

// switch(month) //月份判断

// {

// case 2: //2月

// if(year%4 &&day>28) day=28 //平年,日期最大值为28

// else if(day>29) day=29 //闰年,日期最大值为29

// break

// case 1:case 3:case 5:case 7:case 8:case 10:case 12:if(day>31) day=31break //大月,日期最大值为31

// case 4:case 6:case 9:case 11:if(day>30) day=30break //小月,日期最大值为30

// default: //错误月份

// month=1 //默认1月

// day=1 //默认1日

// break

// }

// if(!day) day=1 //日期最小值为1

// if(!week || week>7) week=1 //周 范围1-7,错误周,默认 周1

// if(hour_mode==H12_Mode &&hour>=12) hour=11 //12小时制,时最大值为11

// else if(hour_mode==H24_Mode &&hour>=24) hour=23 //24小时制,时最大值为23

// if(min>=60) min=59 //分最大值为59

// if(sec>=60) sec=59 //秒最大值为59

//

// year=((year/10)<<4) | (year%10) //转成 BCD码

// month=((month/10)<<4) | (month%10) //转成 BCD码

// day=((day/10)<<4) | (day%10) //转成 BCD码

// hour=((hour/10)<<4) | (hour%10) //转成 BCD码

// if(hour_mode==H12_Mode) hour|=H12_Mode //选择 12小时制

// else hour&=H24_Mode //选择 24小时制

// min=((min/10)<<4) | (min%10) //转成 BCD码

// sec=((sec/10)<<4) | (sec%10) //转成 BCD码

// if(clock_state==ClockHalt) sec|=ClockHalt //选择 时钟停止状态

// else sec&=ClockStart //选择 时钟启动状态

//

// DS1302_WriteByte(Write_Protect,ProtectDis) //取消写保护

// DS1302_WriteByte(Write_Year,year) //输入 BCD码 格式年

// DS1302_WriteByte(Write_Month,month) //输入 BCD码 格式月

// DS1302_WriteByte(Write_Day,day) //输入 BCD码 格式日

// DS1302_WriteByte(Write_Week,week) //输入 BCD码 格式周

// DS1302_WriteByte(Write_Hour,hour) //输入 BCD码 格式时

// DS1302_WriteByte(Write_Min,min) //输入 BCD码 格式分

// DS1302_WriteByte(Write_Sec,sec) //输入 BCD码 格式秒

// DS1302_WriteByte(Write_Protect,ProtectEn) //开启写保护

//}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12267172.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存