/*====================================
GN1302时钟驱动程序案例参考
====================================*/
//调用1602显示驱动,在此文件内已包含51头文件和定义数据类型
#include "LCD1602.h"
/*====================================
IO接口定义
====================================*/
sbit TSCLK = P1^0; //时钟
sbit TIO = P1^1; ? //数据
sbit TRST = P1^2; ?//使能
#define MAIN_Fosc ?11059200UL ?//宏定义主时钟HZ
#define GN1302_W_ADDR 0x80 ? ? //写时钟日历寄存器起始地址
#define GN1302_R_ADDR 0x81 ? ? //读时钟日历寄存器起始地址
//时钟日历暂存数组,秒、分、时、日、月、周、年 初值为= 21年9月1日 周3 00:00:00
//用作上电初始化配置时间使用
uchar TimeData[7]={0, 0, 0, 1, 9, 3, 21};
/*=================================================
*函数名称:Delay_Ms
*函数功能:12T 51单片机自适应主时钟毫秒级延时函数
*说明:需定义MAIN_Fosc(晶振主频单位HZ)
*输入:ms:要延时的毫秒
=================================================*/
void Delay_Ms(INT16U ms)
{
?INT16U i;
?do
?{
?i = MAIN_Fosc / 96000;?
?while(--i); ? ? //96T per loop
?}
?while(--ms);
}
/*=================================================
*函数名称:GN1302_W_Byte
*函数功能:GN1302写一字节数据
*输入:dat:要写入的数据
=================================================*/
void GN1302_W_Byte(uchar dat)
{
uchar i;
for(i = 0; i < 8; i++) //每次写1bit,写8次
{
?TSCLK = 0; ? ?//拉低时钟总线
?TIO = dat & 0x01; ?//从一字节最低位开始写
?TSCLK = 1; ? ?//拉高时钟总线,GN1302把数据读走
?dat >>= 1; ? ?//数据右移一位?
}?
}
/*=================================================
*函数名称:GN1302_R_Byte
*函数功能:GN1302读一字节
*输出:dat:读取的数据
=================================================*/
uchar GN1302_R_Byte()
{
uchar i, dat;
for(i = 0; i < 8; i++) ?//每次写1bit,写8次
{
?TSCLK = 0; ? ? //拉低时钟总线,GN1302把数据放到数据总线上
?dat >>= 1; ? ? ?//数据右移一位,数据从最低位开始读?
?if(TIO) dat |= 0x80;//读取数据
?TSCLK = 1; ? ? //拉高时钟总线
}
return dat; ? ? ?//返回读取的数据
}
/*=================================================
*函数名称:GN1302_W_DAT
*函数功能:写GN1302数据一次写2个字节
*说明:先写命令后写数据
*调用:GN1302_W_Byte()
*输入:cmd:需要写的命令 ,dat:需要些的数据
=================================================*/
void GN1302_W_DAT(uchar cmd, uchar dat)
{
TRST = 0; ? //拉低使能端
TSCLK = 0; ? ? ? ? ?//拉低数据总线
TRST = 1; ? //拉高使能端,开始写数据
GN1302_W_Byte(cmd); ?//写命令
GN1302_W_Byte(dat); ?//写数据
}
/*=================================================
*函数名称:GN1302_R_DAT
*函数功能:读GN1302数据
*说明:先写入命令字节后读出对应数据
*调用: GN1302_W_Byte();GN1302_R_Byte();
*输入: cmd:需要写的命令
*输出: dat:读出的数据
=================================================*/
uchar GN1302_R_DAT(uchar cmd)
{
uchar dat;
TRST = 0; ? //拉低使能端
TSCLK = 0; ? //拉低数据总线
TRST = 1; ? //拉高使能端,开始写数据
GN1302_W_Byte(cmd); ?//写命令
dat = GN1302_R_Byte(); ?//读出数据
return dat; ? //返回读出数据
}
/*=================================================
*函数名称:GN1302_Clear_WP
*函数功能:清除GN1302写保护
*说明:先写入命令0x8e(写控制寄存器)接着向该寄存器写0x00
*调用:GN1302_W_DAT()
=================================================*/
void GN1302_Clear_WP()
{
GN1302_W_DAT(0x8e,0x00); ?//把控制寄存器WP位置0
}
/*=================================================
*函数名称:GN1302_Set_WP
*函数功能:设置GN1302写保护
*说明:先写入命令0x8e(写控制寄存器)接着向该寄存器写0x80
*调用:GN1302_W_DAT()
=================================================*/
void GN1302_Set_WP()
{?
GN1302_W_DAT(0x8e,0x80); //把控制寄存器WP位置1
TRST = 0; ? //拉低使能端
TSCLK = 0; ? //拉低数据总线
}?
/*=================================================
*函数名称:Set_GN1302_Time
*函数功能:设置GN1302时钟日历数据
*说明:把时钟日历暂存数组TimeData数据转换为BCD码并写入到GN1302时钟日历寄存器中
*调用:GN1302_Clear_WP();GN1302_W_DAT();GN1302_Set_WP();
*输入:addr:需要写入寄存器的地址 ,TimeData数组:时钟日历初始值
=================================================*/
void Set_GN1302_Time(uchar addr)
{
uchar i, j;
GN1302_Clear_WP(); ? ? ?//清除写保护
for(i = 0; i < 7; i++) ? ? ?//写入7个字节的时钟初始值
{
?j = TimeData[i]/10; ? ? ? ? ? ? ?//BCD码转换
?TimeData[i] %= 10; ? ? ? ? ? ? ? //BCD码转换
?TimeData[i] += j*16; ? ? ? ? ? ? //BCD码转换
?GN1302_W_DAT(addr, TimeData[i]); //先写GN1302时钟日历起始地址,再写数据
?addr += 2; ? ? ? ? ? ? ? ? ? //时钟日历寄存器地址+2转向下一个寄存器
}
GN1302_Set_WP(); ? ? ? ? ? ? //开起写保护 ?
}
/*=================================================
*函数名称:Read_GN1302_Time
*函数功能:读取GN1302时钟数据
*说明: 读取GN1302时钟数据 返回数据存入时钟日历暂存
?数组TimeData(数据格式BCD码)
*调用:GN1302_Clear_WP();GN1302_R_DAT();GN1302_Set_WP();
*输入: addr:需要读取时钟日历寄存器的起始地址
=================================================*/
void Read_GN1302_Time(uchar addr)
{
uchar i;
GN1302_Clear_WP(); ? ? //清楚些保护
for(i = 0; i < 7; i++) //从GN1302读取7个字节的时钟日历数据
{
?TimeData[i] = GN1302_R_DAT(addr);//先写入要读取数据的寄存器起始地址,再读出数据存入TimeData数组
?addr += 2; ? ? ? ? ? ? ? ? ? //时钟日历寄存器地址+2转向下一个寄存器
}
GN1302_Set_WP(); ? ? ? ?//开起写保护
}?
/*=================================================
*函数名称:main
*函数功能:主函数 1602液晶显示GN1302数据
? ? Date:年-月-日-星期
? ? Time:时:分:秒
=================================================*/
void main()
{
InitLcd1602(); ? ? ? ? ? ? ? //1602初始化
Set_GN1302_Time(GN1302_W_ADDR); //先写入时钟日历寄存器起始地址再设置时钟日历初值
?
LcdShowStr(0,0,"Date:"); ?//1602显示字符串
LcdShowStr(0,1,"Time:"); ?//1602显示字符串
while(1)
{
?Read_GN1302_Time(GN1302_R_ADDR); //先写入时钟日历寄存器起始地址再读出时钟日历写入到TimeData数组中
?DisplayOneStr (5,0,TimeData[6]); //年
?DisplayOneChar (7,0,'-'); ? //-
?DisplayOneStr (8,0,TimeData[4]); //月
?DisplayOneChar (10,0,'-'); ? //-
?DisplayOneStr (11,0,TimeData[3]);//日
?DisplayOneChar (13,0,'-'); ? //-
?DisplayOneStr (14,0,TimeData[5]);//星期
DisplayOneStr (6,1,TimeData[2]); //时
?DisplayOneChar (8,1,':'); ? //:
?DisplayOneStr (9,1,TimeData[1]); //分
?DisplayOneChar (11,1,':'); ? //:
?DisplayOneStr (12,1,TimeData[0]);//秒
?Delay_Ms(1000); ? ? ?//延时1秒
} ?
}
审核编辑?黄昊宇
?
评论