虽然程序大部分是一个网友的(我只改了3个函数),思路也是别人的。可是看在我搞了1天的份上面还是算原创吧,o(∩_∩)o...
注意那个IO口要和电源间接个电阻哦,还有我的外接电源用的手机电池,为这个去买充电电池不划算的
- # include <AT89x52.h>
- /*****************************************
- P0------DB0~DB7
- P1.0------RS
- P1.1------RW
- P1.2------E
- *****************************************/
- # define LCD_DB P0
- sbit LCD_RS=P1^0;
- sbit LCD_RW=P1^1;
- sbit LCD_E=P1^2;
- sbit DS1302_SCLK = P3^4;
- sbit DS1302_IO = P3^3;
- sbit DS1302_RST = P3^5;
- //定义待设置的时间:秒、分、时、日、月、星期、年、控制字
- char table[]={0x00,0x58,0x12,0x8,0x3,0x06,0x06,0x00};
- char table1[]={0x11};
- char table2[]={0x22};
- unsigned char bdata time_rx ;
- sbit time_rx7 = time_rx^7;
- /******定义函数****************/
- # define uchar unsigned char
- # define uint unsigned int
- void LCD_init(void);//初始化函数
- void LCD_write_command(uchar command);//写指令函数
- void LCD_write_data(uchar dat);//写数据函数
- void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-16),y(1-2)
- void delay_n40us(uint n);//延时函数
- //写一个字节数据函数
- void time_write_1(unsigned char time_tx)
- {
- int j; //设置循环变量
- for(j=0;j<8;j++) //连续写8bit
- {
- DS1302_IO = 0; //先设置数据为0
- DS1302_SCLK = 0; //时钟信号拉低
- if(time_tx&0x01) //判断待发送的数据位是0或1
- {
- DS1302_IO = 1; //待发送数据位是1
- }
- time_tx=time_tx>>1; //待发送的数据右移1位
- DS1302_SCLK = 1; //拉高时钟信号
- }
- DS1302_SCLK = 0; //写完一个字节,拉低时钟信号
- }
- //---------------------------------------------
- //读一个字节函数
- unsigned char time_read_1()
- {
- int j; //设置循环变量
- DS1302_IO = 1; //设置为输入方式
- for(j=0;j<8;j++) //连续读取8bit
- {
- DS1302_SCLK = 0; //拉低时钟信号
- time_rx=time_rx>>1; //接收寄存器右移1位
- time_rx7=DS1302_IO; //把接收到的数据放到接收寄存器的最高位
- DS1302_SCLK = 1; //拉高时钟信号
- }
- DS1302_SCLK = 0; //拉低时钟信号
- return(time_rx); //返回读取到的数据
- }
- //DS1302初始化函数
- void ds1302_init()
- {
- DS1302_SCLK = 0; //拉低时钟信号
- DS1302_RST = 0; //复位DS1302
- DS1302_RST = 1; //使能DS1302
- time_write_1(0x8e); //发控制命令
- time_write_1(0); //允许写DS1302
- DS1302_RST = 0; //复位
- }
- //---------------------------------------------
- //---------------------------------------------
- //设置时间函数
- void set_time()
- {
- int i; //定义循环变量
- DS1302_RST = 1; //使能DS1302
- time_write_1(0xbe); //时钟多字节写命令
- for(i=0;i<8;i++) //连续写8个字节数据
- {
- time_write_1(table[i]); //调用写一个字节函数
- }
- DS1302_RST = 0; //复位
- }
- //---------------------------------------------
- //---------------------------------------------
- //设置是否初始化标志
- void set_ytime()
- {
- DS1302_RST = 1; //使能DS1302
- time_write_1(0xc0); //时钟多字节写命令
- time_write_1(table1[0]); //调用写一个字节函数
- DS1302_RST = 0; //复位
- }
- //读取初始化标志函数
- void get_ytime()
- {
- DS1302_RST = 1; //使能DS1302
- time_write_1(0xc1); //发送多字节读取命令
- table2[0]=time_read_1(); //调用读取1个字节数据的函数
- DS1302_RST = 0; //复位DS1302
- }
- //---------------------------------------------
- //读取时间函数
- void get_time()
- {
- int i; //设置循环变量
- DS1302_RST = 1; //使能DS1302
- time_write_1(0xbf); //发送多字节读取命令
- for(i=0;i<7;i++) //连续读取7个字节数据
- {
- table[i]=time_read_1(); //调用读取1个字节数据的函数
- }
- DS1302_RST = 0; //复位DS1302
- }
- //*******初始化函数***************
- void LCD_init(void)
- {
- delay_n40us(10000);
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- LCD_write_command(0x02);//整体显示,关光标,不闪烁
- LCD_write_command(0x0C);//清除屏幕显示
- LCD_write_command(0x06);//设定输入方式,增量不移位
- }
- //********************************
- //********写指令函数************
- void LCD_write_command(uchar dat)
- {
- LCD_E = 0;
- LCD_RS=0;//指令
- LCD_RW=0;//写入
- LCD_DB=dat;
- LCD_E=1;//允许
- delay_n40us(10);//实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
- LCD_E = 0;
- }
- //*******************************
- //********写数据函数*************
- void LCD_write_data(uchar dat)
- {
- LCD_E = 0;
- LCD_RS=1;//数据
- LCD_RW=0;//写入
- LCD_DB=dat;
- LCD_E=1;//允许
- delay_n40us(10);
- LCD_E = 0;
- }
- //********************************
- //*******显示一个字符函数*********
- void LCD_disp_char(uchar x,uchar y,uchar dat)
- {
- uchar address;
- if(y==1)
- address="0x80"+x;
- else
- address="0xc0"+x;
- LCD_write_command(address);
- LCD_write_data(dat);
- }
- void delay_n40us(uint n)
- {
- uint i;
- uchar j;
- for(i=n;i>0;i--)
- for(j=0;j<15;j++)
- ; //
- } //
- //*******************************
- void disp_time()
- {
- LCD_disp_char(3,1,((table[2]&0xf0)>>4)+0x30);
- LCD_disp_char(4,1,(table[2]&0x0f)+0x30);
- LCD_disp_char(5,1,':');
- LCD_disp_char(6,1,((table[1]&0xf0)>>4)+0x30);
- LCD_disp_char(7,1,(table[1]&0x0f)+0x30);
- LCD_disp_char(8,1,':');
- LCD_disp_char(9,1,((table[0]&0xf0)>>4)+0x30);
- LCD_disp_char(10,1,(table[0]&0x0f)+0x30);
- }
- //*********主函数*****************
- void main(void)
- {
- get_ytime();
- if(table2[0]==0x11)
- {
- ;
- }
- else
- {
- ds1302_init(); //调用DS1302初始化函数
- set_time(); //调用设置时间函数
- set_ytime(); //调用设置标志函数
- }
- DS1302_RST = 1; //使能DS1302
- time_write_1(0x90); //充电命令
- time_write_1(0xa5); //打开充电二级管 一个二级管串联一个2K电阻
- DS1302_RST = 0; //复位DS1302
- LCD_init();
- while(1)
- {
- get_time(); //调用取时间函数
- disp_time();
- }
- }
这是我接触到的第一个时钟芯片,编写这个时间模块程序,可是费了不少周折,这里will666博客里面有芯片资料http://blog.ednchina.com/will666/49952/message.aspx
使用的时候,S7偏上的两个脚要连起来,S8也是。这个不难,看wangjin博客上面有电路图,不过WILL66上面S7、S8那个接口图把ps2和时钟标反了。
如果你的还是不能正常显示,显示什么85呀,??呀,o(∩_∩)o...,那就在时钟芯片的IO脚与VCC之间接个上拉电阻吧。1K或者4.7K的都行(我自己是接的一个滑动变阻器)http://group.ednchina.com/329/3374.aspx
调试程序就不帖了,在小组里面找找哦。
还有那个备用电源VCC1可以不接,只是每次开机了上次的时间不会保持,如果要接的话,从资料上面看,要接那种可以充电的电池,因为资料上面说平时VCC2对VCC1充电,当VCC2电压比较低了就用VCC1的电源,就是类似于电脑主板上面的那个电池一样的。
下面是引用一个网友的资料,就是外接电源后,为什么时间还是没有保持的问题,o(∩_∩)o...,因为你每次开机都把时钟芯片初始化了呀。
关于DS1302的初始化也是有技巧的,这是一个可以带备用电池的芯片,放上电池,即使把电源关了,它的时间还是在走的,呵呵,和电脑一样呀!这样 的话,如果它的备用电池不断电,就不用再对它初始化啦,也就是说一辈子不断电,这一辈子它只要初始化一次就行了,但是单片机如果断电再通电,程序又会从头 开始执行,又会执行它的初始化程序,我开始以为只要不破坏它的时钟数据就行,单片机开机时先读一次时钟数据,然后把控制字叠加进去,再写回去就好了,可试 验了好几次都不行,每次都是小时的数据不对了。于是在DS1302暂存RAM中设立一个标志位,只要备用电池不断电,标志就不会消失,每次通电开机时,单 片机检测到这个标志就不再对其初始化,呵呵,一切正常。
浙公网安备 33010602011771号