定时器定时,每秒读取一次ds1302时间。
第一次能够成功读取预设时间,之后就不正常。
1.ds1302头文件
#ifndef _DS1302_H_
#define _DS1302_H_
#include <reg52.h>
sbit DS1302_IO = P3^4; //ds1302串行数据引脚
sbit DS1302_CE = P3^5; //ds1302使能引脚、复位引脚
sbit DS1302_CK = P3^6; //ds1302串行时钟引脚
void DS1302BurstInit(); //ds1302突发模式初始化
void ds1302BurstRead(unsigned char *dat); //ds1302突发模式连续读
#endif
2.ds1302文件
#include "ds1302.h"
//ds1302写字节操作(低位->高位),上升沿写
void ds1302ByteWrite(unsigned char dat) {
unsigned char i=0;
for(i=0; i<8; i++) {
DS1302_IO = dat & 0x01;
dat >>= 1;
DS1302_CK = 1;
DS1302_CK = 0;
}
}
//ds1302读字节操作(低位->高位),下降沿读
unsigned char ds1302ByteRead() {
unsigned char i=0, dat=0;
for(i=0; i<8; i++) {
dat >>= 1;
dat |= (unsigned char)DS1302_IO << 7;
DS1302_CK = 1;
DS1302_CK = 0;
}
return dat;
}
//ds1302单次写操作(向某一寄存器写入一个字节)
void ds1302SingleWrite(unsigned char addr, unsigned char dat) {
DS1302_CE = 1;
ds1302ByteWrite(addr);
ds1302ByteWrite(dat);
DS1302_CE = 0;
}
//ds1302单次读操作(从某一寄存器读出一个字节)
unsigned char ds1302SingleRead(unsigned char addr) {
unsigned char dat = 0;
DS1302_CE = 1;
ds1302ByteWrite(addr);
dat = ds1302ByteRead();
DS1302_CE = 0;
DS1302_CK = 1;
DS1302_IO = 1;
DS1302_IO = 0;
return dat;
}
//ds1302突发模式写操作(连续写入8个字节)
void ds1302BurstWrite(unsigned char *dat) {
unsigned char i=0;
DS1302_CE = 1;
ds1302ByteWrite(0xBE); //发送突发写寄存器指令
//连续写入8个字节
for(i=0; i<8; i++) {
ds1302ByteWrite(dat[i]);
}
DS1302_CE = 0;
}
//ds1302突发模式读操作(连续读取8个字节)
void ds1302BurstRead(unsigned char *dat) {
unsigned char i=0;
DS1302_CE = 1;
ds1302ByteWrite(0xBF); //发送突发读寄存器指令
//连续读取8个字节
for(i=0; i<8; i++) {
*dat++ = ds1302ByteRead();
}
DS1302_CE = 0;
}
//ds1302突发模式初始化
void DS1302BurstInit() {
unsigned char ch=0; //时钟停止标志位
//初始化时间(秒、分、时、日、月、星期、年、写保护位)(2000年1月1日星期六 00:00:00)
unsigned char code InitTime[] = {
0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00
};
//初始化ds1302通信引脚
DS1302_CE = 0;
DS1302_CK = 0;
ch = ds1302SingleRead(0x81); //读取秒寄存器
//由秒寄存器最高位CH的值判断DS1302是否停止工作(已停止工作则初始化时钟)
if((ch & 0x80) != 0) {
ds1302SingleWrite(0x8E, 0x00); //撤销写保护功能,允许写入数据
ds1302BurstWrite(InitTime);
}
ds1302SingleWrite(0x8E, 0x80); //打开写保护功能,禁止写入数据
}
3.主文件
#include <reg52.h>
#include "ds1302.h"
#include "lcd1602.h"
bit flag200ms;
void timeProcessDisplay(unsigned char *dat);
void ConfigInterrupt();
void Time0();
void main() {
unsigned char time[8] = {0};
ConfigInterrupt();
DS1302BurstInit();
lcdInit();
lcdFullclear();
flag200ms = 1;
while(1) {
if(flag200ms) {
flag200ms = 0;
ds1302BurstRead(time);
timeProcessDisplay(time);
}
}
}
//时间处理及显示
void timeProcessDisplay(unsigned char *dat) {
static unsigned char secBackup = 0x60; //秒备份值(判断是否需要刷新显示,确保首次刷新显示)
unsigned char str[12] = {0};
if(secBackup != dat[0]) {
lcdFullclear();
str[0] = '2';
str[1] = '0';
str[2] = (dat[6] >> 4) + '0';
str[3] = (dat[6]&0x0f) + '0';
str[4] = '-';
str[5] = (dat[4] >> 4) + '0';
str[6] = (dat[4]&0x0f) + '0';
str[7] = '-';
str[8] = (dat[3] >> 4) + '0';
str[9] = (dat[3]&0x0f) + '0';
str[10] = '\0';
lcdShowStr(0, 2, str);
str[0] = (dat[5]&0x0f) + '0';
str[1] = '\0';
lcdShowStr(0, 13, str);
str[0] = (dat[2] >> 4) + '0';
str[1] = (dat[2]&0x0f) + '0';
str[2] = ':';
str[3] = (dat[1] >> 4) + '0';
str[4] = (dat[1]&0x0f) + '0';
str[5] = ':';
str[6] = (dat[0] >> 4) + '0';
str[7] = (dat[0]&0x0f) + '0';
str[8] = '\0';
lcdShowStr(1, 4, str);
secBackup = dat[0];
}
}
//中断配置
void ConfigInterrupt() {
TMOD &= 0xf0;
TMOD |= 0x01;
//1ms
TH0 = 0xfc;
TL0 = 0x82;
ET0 = 1;
EA = 1;
TR0 = 0;
}
//定时器0中断
void Time0() interrupt 1 {
static unsigned char time200ms = 0;
//1ms
TH0 = 0xfc;
TL0 = 0x82;
time200ms++;
if(time200ms >= 200) {
time200ms = 0;
flag200ms = 1;
}
}
lcd1602程序文件应该没问题,就不贴出来占地方了。时间数据处理函数测试过应该也没问题。用的是普中的板子。
烦请网友帮忙看一下哪里出问题了,自己检查好久都没找出来问题。