本帖最后由 jianwei2030 于 2017-9-3 21:12 编辑
自己做了一个万年历时钟,利用STC15W408AS单片机,时钟芯片采用DS1302。当前自己参考网上写了时间读取的程序,在实验板走时正常,但是断电再上电后无法保存时间,程序在首次上电后会初始化一个固定的时间,每次都得自己重新调时。看到网上有种说法是给1302写入标志位,每次系统上电后检测这个标志位,如果能够检测到就不初始化时间,直接读取;如果检测不到标志位就初始化。但是按照这种方法试过后仍然不见效果,请大家帮忙看看我这程序该怎么修改合适?
电路部分:
以下是我的程序:
1302部分:
- #include<STC15W.h>
- #define uchar unsigned char
- #define uint unsigned int
- /* 宏定义写DS1302的地址 */
- #define write_sec_add 0x80 //秒数据地址 1000 0000
- #define write_min_add 0x82 //分数据地址 1000 0010
- #define write_hr_add 0x84 //时数据地址 1000 0100
- #define write_week_add 0x86 //星期数据地址 1000 0110
- #define write_month_add 0x88 //月数据地址 1000 1000
- #define write_day_add 0x8a //日数据地址 1000 1010
- #define write_year_add 0x8c //年数据地址 1000 1100
- #define write_control_add 0x8e //控制数据地址 1000 1110
- #define write_charger_add 0x90 //可编程涓流充电地址 1001 0000
- #define write_clkburst_add 0xbe //时钟脉冲串地址
- #define write_RAM0_add 0xc0 //RAM0寄存器写地址 1100 0000
- /* 宏定义读DS1302的地址 */
- #define read_sec_add 0x81 //秒数据地址 1000 0001
- #define read_min_add 0x83 //分数据地址 1000 0011
- #define read_hr_add 0x85 //时数据地址 1000 0101
- #define read_week_add 0x87 //星期数据地址 1000 0111
- #define read_month_add 0x89 //月数据地址 1000 1001
- #define read_day_add 0x8b //日数据地址 1000 1011
- #define read_year_add 0x8d //年数据地址 1000 1101
- #define read_control_add 0x8f //控制数据地址 1000 1111
- #define read_charger_add 0x91 //可编程涓流充电地址 1001 0001
- #define read_clkburst_add 0xbe //时钟脉冲串地址
- #define read_RAM0_add 0xc1 //RAM0寄存器读地址 1100 0001
- //#define P2M1 = 0x00; //0000 0000
- //#define P2M0 = 0x04; //0000 0100
- uchar sec,min,hr,week,mouth,day,year,ram_data;
- sbit sclk=P2^1;
- sbit io=P2^2;
- sbit ce=P2^3;
- void write1302_time(uchar address,uchar dat) //写入数据给1302
- {
- uchar i;
- ce=0; //禁止读写数据
- sclk=0;
- for(i=0;i<8;i++) //写地址
- {
- ce=1; //允许读写数据
- sclk=0;
- io=address&0x01;
- address>>=1;
- sclk=1;
- }
- for(i=0;i<8;i++) //写数据
- {
- ce=1; //允许读写数据
- sclk=0;
- io=dat&0x01;
- dat>>=1;
- sclk=1;
- }
- ce=0;
- }
- uchar read1302_time(uchar address) //从1302读取时间数据
- {
- uchar i,num;
- ce=0; //禁止读写数据
- for(i=0;i<8;i++)
- {
- ce=1;
- sclk=0;
- io=address&0x01;
- address>>=1;
- sclk=1;
- }
- for(i=0;i<8;i++)
- {
- if(io==1)
- num=num|0x80;
- else
- num=num|0x00;
- sclk=1;
- num>>=1;
- sclk=0;
- }
- ce=0;
- return num;
- }
- void init_1302() //初始化函数 设置时间
- {
- read_ram_data = read1302_time(read_RAM0_add);
- if(rread_ram_data!=0xf0)
- {
- write1302_time(0x8e,0x00); //保护取消,可以进行读写操作
- write1302_time(write_sec_add,0x00);//写入初始秒时间 0101 0110
- write1302_time(write_min_add,0x35);//写入初始分时间 0101 0110
- write1302_time(write_hr_add,0x22); //写入初始时时间 0101 0110
- write1302_time(write_week_add,0x06); //写入初始周时间 0101 0110
- write1302_time(write_month_add,0x08); //写入初始月时间 0101 0110
- write1302_time(write_day_add,0x12); //写入初始日时间 0101 0110
- write1302_time(write_year_add,0x17); //写入初始年时间 0101 0110
- write1302_time(0x90,0xa5); //使能涓流充电, 1010 0101
- write1302_time(write_RAM0_add,0xf0); //往RAM寄存器中写入0xf0数据,因为RAM有掉电丢失特点,所以进入初始化函数的时候首先判断这个寄存器是否还有数据
- write1302_time(0x8e,0x80); //保护启动,禁止对1302写操作
- }
- }
- void xianshi_data() //将从1302读出的二进制数据转换为十进制
- {
- uchar read_sec, read_min, read_hr, read_week, read_mouth, read_day, read_year;
- read_sec = read1302_time(read_sec_add); //从“read1302_time”函数取得返回值num的数据
- sec = ((read_sec&0x70)>>4)*10+(read_sec&0x0f); //十进制“秒”
- read_min = read1302_time(read_min_add);
- min = ((read_min&0x70)>>4)*10+(read_min&0x0f); //十进制“分”
- read_hr = read1302_time(read_hr_add);
- hr = ((read_hr&0x70)>>4)*10+(read_hr&0x0f); //十进制“时”
- read_week = read1302_time(read_week_add);
- week = ((read_week&0x70)>>4)*10+(read_week&0x0f); //十进制“周”
- read_day = read1302_time(read_day_add);
- day = ((read_day&0x70)>>4)*10+(read_day&0x0f); //十进制“日”
- read_mouth = read1302_time(read_month_add);
- mouth = ((read_mouth&0x70)>>4)*10+(read_mouth&0x0f); //十进制“月”
- read_year = read1302_time(read_year_add);
- year = ((read_year&0x70)>>4)*10+(read_year&0x0f); //十进制“年”
- }
复制代码
主函数部分:
- #include<STC15W.h>
- #include"1302.h"
- #include"18B20.h"
- #include"display.h"
- #include"keyboard.h"
- #define uchar unsigned char
- #define uint unsigned int
- //#define P2M1_set 0x00 //设置P2口工作模式 0000 0000
- //#define P2M0_set 0x0d //设置P2口工作模式 0000 1110
- uchar num;
- /*************************延时函数*************************/
- void delay(uint a) // 1ms延时程序(12MHz 10倍于51单片机速度时)
- {
- uint i;
- while(--a != 0)
- {
- for(i = 0;i < 600;i++);
- }
- }
- /***************************************初始化IO口状态**************************************/
- //void IO_init(void)
- //{
- //P2M1 = P2M1_set;
- //P2M0 = P2M0_set;
- //}
- /**************************************外部中断INT2初始化函数 **************************************/
- void INT2_init()
- {
- INT_CLKO |= 0x10;
- EA = 1;
- }
- void main()
- {
- INT2_init();
- // IO_init();
- // read_ram();
- init_1302();
- init_18b20();
- while(1)
- {
- display_service();
- display_qiehuan();
- }
- }
复制代码
这是网上找到的别人的回答:
https://zhidao.baidu.com/question/345394758.html
|