12864 1302 实时时钟

更新时间:2023-06-04 08:23:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

//此程序为12864液晶显示ds1302实时时钟,程序亲测正确

#define TRUE 1

#define FALSE 0

#include "12864.h" //包含12864液晶函数文件,在本文档的最下面

/*

cpu晶振 8Mhz

ds1302晶振 32.768khz

*/

/******************RTC常量******************/

#define RTC_CLK PB0

#define RTC_DATA PB1

#define RTC_CS PB2

//命令

#define RD 0x01

#define WR 0x00

#define C_SEC 0x80 //秒

#define C_MIN 0x82 //分

#define C_HR 0x84 //时

#define C_DAY 0x86 //日

#define C_MTH 0x88 //月

#define C_WK 0x8A //星期 DATE

#define C_YR 0x8C //年

#define C_WP 0x8E //控制(写保护)

#define C_CHARGE 0x90 //涓流充电

#define C_BURST 0xBE //时钟多字节

//配置

#define CLK_HALT 0x80 //停止时钟控制位 SECOND bit7

#define CLK_START 0x00 //启动时钟

#define M12_24 0x80 //12/24小时值选择位 HOUR bit7

#define PROTECT 0x80 //写保护控制位 CONTROL bit7

#define UPROTECT 0x00 //写保护控制位 CONTROL bit7

//涓流充电控制常量

#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors

#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors

#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)

//RAM 命令

#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位

void Delayus(uint US)

{

uint i;

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

US=US*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值 for( i=0;i<US;i++);

}

void Delayms(uint MS)

{

uint i,j;

for( i=0;i<MS;i++)

for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值 }

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

函数名称: DS1302_init

功 能: 初始化DS1302的数据接口

参 数: 无

返回值 : 无

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

void DS1302_portinit(void)

{

DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出

}

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

函数名称: DS1302_writeB

功 能: 向DS1302写入一个字节数据(没有RST操作)

参 数: byte--要写入的数据

返回值 : 无

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

void DS1302_writeB(uchar byte)

{

uchar i;

for(i=0;i<8;i++) //8位数据计数

{

PORTB&=~BIT(RTC_CLK); //拉低时钟端

if(byte&0x01) //当前位是否是1

{

PORTB|=BIT(RTC_DATA); //当前位是1,拉高数据端

}

else

{

PORTB&=~BIT(RTC_DATA); //当前位是0,拉低数据端

}

Delayus(10); //调整时钟和脉冲宽度

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

PORTB|=BIT(RTC_CLK); //时钟上升沿(DS1302采样数据)

byte>>=1; //数据右移1位,为送出新数据位做准备

}

}

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

函数名称: DS1302_readB

功 能: 从DS1302读出一个字节数据(没有RST操作)

参 数: 无

返回值 : byte--读出的数据

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

uchar DS1302_readB(void)

{

uchar i,byte=0;

DDRB&=~BIT(RTC_DATA); //将数据端口设置为输入

PORTB&=~BIT(RTC_DATA); //无上拉电阻

for(i=0;i<8;i++) //8位数据计数

{

byte>>=1; //保存读入的数据位

PORTB|=BIT(RTC_CLK); //时钟上升沿

Delayus(10); //延时,调整时钟脉冲宽度

PORTB&=~BIT(RTC_CLK); //时钟下降沿,DS1302输出数据位

Delayus(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)

if(PINB&BIT(RTC_DATA)) //当前位是否是高电平

{

byte|=BIT(PB7); //是高电平就将返回数据的当前位置1

}

else

{

byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0

}

}

DDRB|=BIT(RTC_DATA); //最后将数据端口设置为输出

return byte; //返回读出的数据

}

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

函数名称: DS1302_writeD

功 能: 向DS1302的某个地址写入一个字节数据

参 数: addr--地址值(寄存器或RAM)

data--要写入的地址

返回值 : 无

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

void DS1302_writeD(uchar addr,uchar data)

{

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

PORTB&=~BIT(RTC_CS); //拉低片选端

PORTB&=~BIT(RTC_CLK); //拉低时钟端

Delayus(10);

PORTB|=BIT(RTC_CS); //拉高片选端

Delayus(10); //调整片选脉冲

DS1302_writeB(addr); //写入操作命令(地址)

Delayus(10);

PORTB&=~BIT(RTC_CLK); //拉低时钟端

Delayus(10);

DS1302_writeB(data); //写入数据

PORTB&=~BIT(RTC_CLK); //拉低时钟端

Delayus(10); //调整片选脉冲

PORTB&=~BIT(RTC_CS); //拉低片选端

}

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

函数名称: DS1302_readD

功 能: 从DS1302的某个地址读出一个字节数据

参 数: addr--地址值(寄存器或RAM)

返回值 : data--读出的数据

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

uchar DS1302_readD(uchar addr)

{

uchar data;

PORTB&=~BIT(RTC_CS); //拉低片选端

PORTB&=~BIT(RTC_CLK); //拉低时钟端

Delayus(10);

PORTB|=BIT(RTC_CS); //拉高片选端

Delayus(10); //调整片选脉冲

DS1302_writeB(addr); //写入操作命令(地址)

Delayus(10);

data=DS1302_readB(); //读出数据

Delayus(10);

PORTB&=~BIT(RTC_CLK); //拉低时钟端

PORTB&=~BIT(RTC_CS); //拉低片选端

return data; //返回读出的数据

}

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

函数名称: DS1302_setT

功 能: 设置DS1302的时间

参 数: ptTimeD--设置时间数组指针

返回值 : 无

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

void DS1302_setT(uchar ptTimeD[])

{

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

uchar i;

uchar addr = 0x80; //写入地址从秒寄存器开始

DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作

Delayms(5);

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

{

DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 时 日 月 星期 年 addr+=2;

Delayms(1);

}

DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作 }

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

函数名称: DS1302_getT

功 能: 读取DS1302的当前时间

参 数: time[]--读取的时间数组

返回值 : 无

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

void DS1302_getT(uchar time[])

{

uchar i;

////////下面的是单次读写//////////////////////////

/* uchar addr = 0x80; //读取地址从秒寄存器开始 for(i=0;i<7;i++)

{

time[i]=DS1302_readD(addr|RD); // 秒 分 时 日 月 星期 年 addr+=2;

}*/

////////////////////////////////////////////////////

/////////下面是多字节读取///////////////

PORTB&=~BIT(RTC_CS); //拉低片选端

Delayus(10);

PORTB|=BIT(RTC_CS); //拉高片选端

Delayus(10); //调整片选脉冲

DS1302_writeB(0xbf); // 0xbf:时钟多字节读取命令

for (i=0;i<8;i++) //时间数据的存放格式是:

{ //秒,分,时,日,月,星期,年,控制

time[i]=DS1302_readB(); //【7个数据(BCD格式)+1个控制】

}

PORTB&=~BIT(RTC_CS); //拉低片选端

///////////////////////////////////////////////

PORTB&=~BIT(RTC_CLK); //拉低时钟端(时钟端在不操作时为低)

}

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

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

函数名称: DS1302_check

功 能: 检测DS1302是否正常工作

参 数: 无

返回值 : exist--为TRUE为检测到DS1302,为FALSE为没检测到

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

uchar DS1302_check(void)

{

uchar exist;

DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令

DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5

exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0

if(exist==0xA5)

{

exist=TRUE; //如果读取值与写入值相等,返回TRUE

}

else

{

exist=FALSE; //如果读取值与写入值不相等,返回FALSE }

return exist;

}

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

函数名称: DS1302_init

功 能: 初始化DS1302

参 数: 无

返回值 : 无

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

void DS1302_init(void)

{

DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令

DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作 DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作 }

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

函数名称: BCD_ASCII

功 能: 将压缩BCD码转换成ascii码

参 数: BCD--将要转换的压缩BCD码

ptasc--转换后的ASCII码数组指针

返回值 : 无

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

void BCD_ASCII(uchar BCD,uchar ptasc[])

{

ptasc[0]=BCD/16|0x30; //0X58 35 38 //转换十位

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

ptasc[1]=BCD&0x0F|0x30; //转换个位

}

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

函数名称: Disp_time

功 能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)

参 数: time[]--时间数组

返回值 : 无

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

void Disp_time(uchar time[])

{

uchar i,asc[2],j;

uchar line1[12]={' ','2','0',0,0,'-',0,0,'-',0,0,'\0'}; //显示第1行的字符数组

uchar line2[10]={' ',0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组

for(i=0;i<3;i++) //为第2行的字符数组赋值

{

BCD_ASCII(time[2-i],asc);

line2[i*3+1]=asc[0];

line2[i*3+2]=asc[1];

}

BCD_ASCII(time[6],asc); //为第1行的年赋值

line1[3]=asc[0];

line1[4]=asc[1];

BCD_ASCII(time[4],asc); //为第1行的月赋值

line1[6]=asc[0];

line1[7]=asc[1];

BCD_ASCII(time[3],asc); //为第1行的日赋值

line1[9]=asc[0];

line1[10]=asc[1];

BCD_ASCII(time[5],asc); //为第1行的星期赋值

j=asc[1];

write_com(0x95);

switch(j)

{

case 49:

hz_disp("星期一");

break;

case 50:

hz_disp("星期二");

break;

case 51:

hz_disp("星期三");

break;

case 52:

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

hz_disp("星期四");

break;

case 53:

hz_disp("星期五");

break;

case 54:

hz_disp("星期六");

break;

case 55:

hz_disp("星期日");

break; default:break;

}

write_com(0x81); //第1行从第2个位置开始显示

hz_disp(line1); //第1行显示

write_com(0x90); //第2行从第1个位置开始显示

hz_disp(line2); //第2行显示

}

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

函数名称: main

功 能: 在12864液晶上显示当前时间

参 数: 无

返回值 : 无

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

void main(void)

{

uchar settime[7]={0x00,0x04,0x09,0x013,0x04,0x03,0x11};//设置的秒,分,时,日,月,星期,年

uchar gettime[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//保存当前时间的数组 LcdIni(); //初始化12864液晶

DS1302_portinit(); //初始化DS1302的三根数据线

DS1302_init(); //启动振荡器,DS1302开始工作

DS1302_setT(settime); //设置初始时间

while(1) //以下程序完成显示和设置时间

{

DS1302_getT(gettime); //获得当前时间

Disp_time(gettime); //显示当前时间

}

}

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

/*------------------包含的12864头文件--------------------------*/

#include <iom16v.h>

#include<macros.h>

#define uchar unsigned char

#define uint unsigned int

#define LcdBus PORTC

const uchar rs=3;

const uchar rw=4;

const uchar en=5;

const uchar psb=6;

const uchar rst=7;

/*------------------忙检查--------------------------*/

void ChkBusy(void)

{

DDRC=0X00; //设置为输入

PORTC=0X00;

PORTD &=~BIT(rs);

PORTD |=BIT(rw);

PORTD |=BIT(en);

while(PINC & 0X80);

PORTD &=~BIT(en);

DDRC=0XFF; //设置为输出

}

/*------------------us延时子程序-----------------------------*/

void delayus(uint us)

{ uint i;

us=us*5/4;

for(i=0;i<us;i++);

}

/*------------------ms延时子程序-----------------------------*/

void delayms(uint ms)

{ uint i,j;

for(i=0;i<ms;i++)

for(j=0;j<1141;j++);

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

}

/*------------------清屏命令--------------------------*/

void clrscreen(void)

{

write_com(0x01);

delayms(2);

}

/*------------------初始化LCD--------------------------*/

void LcdIni(void)

{

DDRC=0XFF;

PORTC=0XFF;

DDRD=0XFF;

PORTD=0XFF;

PORTD &= ~BIT(rst);

NOP();

PORTD |=BIT(rst); //复位

delayms(5);

write_com(0x30); //选择基本指令集,选择8bit数据流

delayms(5);

write_com(0x01); //清除显示,并且设定地址指针为00H

delayms(5);

write_com(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位

delayms(5);

write_com(0x0c); //开显示(无游标、不反白)

}

/*------------------写指令--------------------------*/

void write_com(uchar com)

{

ChkBusy();

PORTD &=~BIT(rs);

PORTD &=~BIT(rw);

PORTD &=~BIT(en);

PORTC =com;

PORTD |=BIT(en);

delayus(10);

此程序为12864液晶显示ds1302实时时钟,程序经本人修改后亲测正确。硬件连接说明很详细。适合给新手学习。

PORTD &=~BIT(en);

}

/*------------------写数据--------------------------*/ void write_data(uchar dat)

{

ChkBusy();

PORTD |=BIT(rs);

PORTD &=~BIT(rw);

PORTD &=~BIT(en);

PORTC=dat;

PORTD |=BIT(en);

delayus(10);

PORTD &=~BIT(en);

}

/*------------------显示字符串--------------------------*/ void hz_disp(uchar *s)

{

while(*s>0)

{ write_data(*s);

s++;

delayus(50);

}

}

本文来源:https://www.bwwdw.com/article/tyl1.html

Top