标题:
单片机+DS1302驱动程序时间加减出错
[打印本页]
作者:
danq
时间:
2020-8-29 14:37
标题:
单片机+DS1302驱动程序时间加减出错
DS1302驱动程序
AIP1722液晶驱动显示
代码如下:
TimeArray[4],TimeArray[5]的加减是否正确,结果出来时TimeArray[4]减到0,再减下去就是95,TimeArray[5]到0时,再减下去显示15;
不知道什么原因,求大神!
/**************************************************
单片机-->DS1302时钟模块
SCLK 7 - P0.5
IO 6 - P0.4
CE 5 - P0.3
****************************************************/
#include "n76e003.h"
#include "intrins.h"
#include "Function_Define.h"
#define uchar unsigned char
#define uint unsigned int
sbit CLK = P1^1 ; //时钟
sbit CS = P1^2 ; //片选
sbit DIN = P1^0 ; //数据
sbit SCLK= P0^5 ; //DS1302时钟
sbit DSIO= P0^4 ; //DS1302数据
sbit RST = P0^3 ; //DS1302CE
sbit LED = P0^2 ;
sbit K1 = P0^1 ; //按键1
sbit K2 = P0^0 ; //按键2
sbit K3 = P1^3 ; //按键3
sbit K4 = P1^4 ; //按键4
uchar TimeArray[8]={20,21,5,21,9,20,52,2};//空2020年2月22日8时20分52秒2周 数组:array
uchar ary[8]; //空年月日时分秒周
uchar Dis[7];
uchar KEY_count=0;
uchar code Table[]={0x5f,0x06,0x6b,0x2f,0x36,0x3d,0x7d,0x07,0x7f,0x3f};//显示数字0-9
uchar code Letter[]={0x01,0x02,0x04,0x08,0x80}; //地址0xc2单独带字母:SCENT\WORK\PAUSE\EVENT\NULL\NULL\NULL\ON
uchar code Week[]={0x01,0x02,0x04,0x08}; //地址0xc6单独带字母:THU\FRI\SAT\SUN
uchar code OFF[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf}; //地址0xc3数字带OFF符号(加0x80)第一数码管
uchar code MON[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf}; //地址0xcf数字带MON符号(加0x80)第二数码管
uchar code TUE[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf}; //地址0xce数字带TUE符号(加0x80)第三数码管
uchar code Colon[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf};//地址0xcb数字带 :符号(加0x80)第四数码管
uchar code WED[]={0xDf,0x86,0xeb,0xaf,0xb6,0xbd,0xfd,0x87,0xff,0xbf}; //地址0xc7数字带WED符号(加0x80)第五数码管
uchar code Week_Address[]={0xcf,0xce,0xc7,0xc6}; //星期地址,0xc6含星期四、星期五、星期六、星期日
//MON:(0xcf,MON[*])、TUE:(0xce,TUE[*])、WED:(0xc7,WED[*])、THU:(0xc6,0x01)、FRI(0xc6,0x02)、SAT(0xc6,0x04)、SUN(0xc6,0x08)//带字母数字地址及数据
#define sec_add 0x80 //秒寄存器写操作命令字
#define min_add 0x82 //分寄存器写操作命令字
#define hour_add 0x84 //时寄存器写操作命令字
#define day_add 0x86 //日寄存器写操作命令字
#define mon_add 0x88 //月寄存器写操作命令字
#define week_add 0x8a //周寄存器写操作命令字
#define year_add 0x8c //年寄存器写操作命令字
#define ctrl_add 0x8e //控制寄存器写操作命令字
#define cha_add 0x90 //涓流充电寄存器写操作命令字
#define clk_add 0xbe //时钟突发寄存器写操作命令字
void Delay_xms(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void Write_1722_byte(uchar DATA) //写字节
{
uchar i;
CS=0;
for(i=8;i>=1;i--)
{
CLK = 0; //时钟拉低,写数据
DIN = DATA & 0x01; //DATA & 10000000,读取最高位写入max7219,最先发送高位(从左往右D7-D0)
CLK = 1; //时钟拉高,送数据
DATA = DATA >> 1; //左移1位,重新&运算,读取最高位写入max7219,从右往左写
}
}
void Write_1722_com(uchar com) //写指令
{
CS=0;
Write_1722_byte(com);
CS=1;
}
void TM1722_Write_Word(uchar addr,uchar dat) //写数据
{
Write_1722_byte(addr);
Write_1722_byte(dat);
Delay_xms(10);
CS=1;
}
void Init_1722(void)
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
P00_PushPull_Mode;
P01_PushPull_Mode;
P02_PushPull_Mode;
P03_PushPull_Mode;
P04_PushPull_Mode;
P05_PushPull_Mode;
P10_PushPull_Mode;
P11_PushPull_Mode;
P12_PushPull_Mode;
Write_1722_com(0x00);
Write_1722_com(0x40);
Write_1722_com(0xc0);
Write_1722_com(0x97); //亮度
}
void Init_qingping() //清屏程序
{
TM1722_Write_Word(0xc2,0x00);
TM1722_Write_Word(0xc3,0x00);
TM1722_Write_Word(0xc6,0x00);
TM1722_Write_Word(0xc7,0x00);
TM1722_Write_Word(0xca,0x00);
TM1722_Write_Word(0xcb,0x00);
TM1722_Write_Word(0xce,0x00);
TM1722_Write_Word(0xcf,0x00);
}
/*************向 DS1302 写入一字节数据***************/
void DS1302_Write_DATA(uchar add, uchar dat)
{
uchar i;
RST=1; //写入控制字节: add
add=add&0xfe; // 最低位置低
for(i=0;i<8;i++) //依次写入控制字的八位
{
if(add&0x01) // 若 add与 0x01 按位与的结果为 0x01(真)
DSIO=1; //向 DS1302 写入 1
else //否则若 add 与 0x01 按位与的结果不为 0x01(假)
DSIO=0; //向 DS1302 写入 0
SCLK=1; //时钟高电平
SCLK=0; //时钟低电平
add=add>>1; //add 依次由高位向低位右移
}
for(i=0;i<8;i++) //依次写入数据的八位
{
if(dat&0x01) //若 dat 与 0x01 按位与的结果为 0x01(真)
DSIO=1; //向 DS1302 写入 1
else //否则若 dat 与 0x01 按位与的结果不为 0x01(假)
DSIO=0; //向 DS1302 写入 0
SCLK=1; //时钟高电平
SCLK=0; //时钟低电平
dat=dat>>1; //dat 依次由高位向低位右移
}
RST=0; //停止 DS1302 总线
}
uchar DS1302_Read_Bit(uchar add) //从 DS1302 读出一字节数据
{
uchar i,tem;
RST=1; //写入目标地址: add
add=add|0x01; //最低位置高
for(i=0;i<8;i++) //依次写入控制字的八位
{
if(add&0x01) //若 add 与 0x01 按位与的结果为 0x01(真)
DSIO=1; //向 DS1302 写入 1
else //否则若 add与 0x01 按位与的结果不为 0x01(假)
DSIO=0; //向 DS1302 写入 0
SCLK=1; //时钟高电平
SCLK=0; //时钟低电平
add=add>>1; //add 依次由高位向低位右移
}
//输出数据: temp
for(i=0;i<8;i++) //依次读出数据的八位
{
tem=tem>>1; //dat 依次由高位向低位右移
if(DSIO) //若 SDA=1
tem|=0x80; //就执行 tem 与 0x80 按位或再赋给 tem,取高位的 1
else //若 SDA=0
tem&=0x7f; //就执行 tem 与 0x7f 按位与再赋给 tem,取高位的 0
SCLK=1; //时钟高电平
SCLK=0; //时钟低电平
}
RST=0; //停止 DS1302 总线
return tem; //返回 tem 的值
}
/**************向 DS1302 写入时钟数据*******************/
void Write_1302CLK()
{
uchar i,tmp;
for(i=0;i<8;i++)
{ //BCD 处理
tmp=TimeArray[i]/10;
ary[i]=TimeArray[i]%10;
ary[i]=ary[i]+tmp*16; //十进制转换为十六进制,ary[]={0x20,0x11,0x06,0x27,0x13,0x33,0x00,0x01}
}
DS1302_Write_DATA(ctrl_add,0x00); //关闭写保护
DS1302_Write_DATA(sec_add,0x80); //暂停
//DS1302_Write_DATA(cha_add,0xa9); //涓流充电
DS1302_Write_DATA(year_add,ary[1]); //年
DS1302_Write_DATA(mon_add,ary[2]); //月
DS1302_Write_DATA(day_add,ary[3]); //日
DS1302_Write_DATA(hour_add,ary[4]); //时
DS1302_Write_DATA(min_add,ary[5]); //分
DS1302_Write_DATA(sec_add,ary[6]); //秒
DS1302_Write_DATA(week_add,ary[7]); //周
DS1302_Write_DATA(ctrl_add,0x80); //打开写保护
//将ary[]中的年月日时分秒周的十六进制数据写入 DS1302
}
/**********************从 DS1302 读出时钟数据********************************/
void Read_1302CLK()
{
uchar i,tmp; //从 DS1302 读出的年月日时分秒周的十六进制数据存入 ary[]
ary[1]=DS1302_Read_Bit(year_add); //年
ary[2]=DS1302_Read_Bit(mon_add); //月
ary[3]=DS1302_Read_Bit(day_add); //日
ary[4]=DS1302_Read_Bit(hour_add); //时
ary[5]=DS1302_Read_Bit(min_add); //分
ary[6]=DS1302_Read_Bit(sec_add); //秒
ary[7]=DS1302_Read_Bit(week_add); //周
for(i=0;i<8;i++) //BCD 处理
{
tmp=ary[i]/16; //十位
TimeArray[i]=ary[i]%16; //个位
TimeArray[i]=TimeArray[i]+(tmp*10); //十六进制转换为十进制
} //将每个十六进制数转换为十进制数存入 TimeArray[]
}
void Arrange() //时间读取处理转换函数
{
Dis[0]=Table[TimeArray[4]/10]; //时
Dis[1]=Table[TimeArray[4]%10];
Dis[2]=0x40; //显示"-"
Dis[3]=Table[TimeArray[5]/10]; //分
Dis[4]=Table[TimeArray[5]%10];
Dis[5]=0x40;
Dis[6]=Table[TimeArray[6]/10]; //秒
Dis[7]=Table[TimeArray[6]%10];
TM1722_Write_Word(0xc3,Dis[7]);//1数码管
TM1722_Write_Word(0xcf,Dis[0]);//2数码管
TM1722_Write_Word(0xce,Dis[1]);//3数码管
TM1722_Write_Word(0xcb,Dis[3]);//4数码管
TM1722_Write_Word(0xc7,Dis[4]);//5数码管
}
void Standby_Colon(uchar TimeR0,uchar TimeR1) //调整时间和星期时闪烁
{
uchar j=0,k=0;
static uchar display_count=0;
display_count++;
if(display_count>120)
{
display_count=1;
}
if(KEY_count==1)
{
j=60;
}
else if(KEY_count==2)
{
k=60;
}
if(display_count>j)
{
TM1722_Write_Word(0xcf,Table[TimeR0/10]);//2数码管
TM1722_Write_Word(0xce,Table[TimeR0%10]);//3数码管
}
else
{
TM1722_Write_Word(0xcf,0x00);//2数码管
TM1722_Write_Word(0xce,0x00);//3
}
if(display_count>k)
{
TM1722_Write_Word(0xcb,Table[TimeR1/10]);//4数码管
TM1722_Write_Word(0xc7,Table[TimeR1%10]);//5数码管
}
else
{
TM1722_Write_Word(0xcb,0x00);//4数码管
TM1722_Write_Word(0xc7,0x00);//5
}
}
void Adjust_Time()
{
Standby_Colon(TimeArray[4],TimeArray[5]);
if(KEY_count==0)
{
Arrange();
}
if(KEY_count==1)
{
if(K3==0||K4==0)
{
if(!K3)
{
TimeArray[4]++; //小时
while(K3==0||K4==0);
if(TimeArray[4]>=24)
{
TimeArray[4]=0;
}
}
else if(!K4)
{
TimeArray[4]--;
while(K3==0||K4==0);
if(TimeArray[4]<=0)
{
TimeArray[4]=23;
}
}
}Write_1302CLK();
}
else if(KEY_count==2)
{
if(K3==0||K4==0)
{
if(!K3)
{
TimeArray[5]++; //分钟
while(K3==0||K4==0);
if(TimeArray[5]>59)
{
TimeArray[5]=0;
}
}
else if(!K4)
{
TimeArray[5]--;
while(K3==0||K4==0);
if(TimeArray[5]<0)
{
TimeArray[5]=59;
}
}
}Write_1302CLK();
}
}
void main()
{
Init_1722();
Init_qingping(); //清屏程序
Write_1302CLK();
Read_1302CLK();
Delay_xms(5);
while(1)
{
Read_1302CLK();
Adjust_Time();
}
}
void timer0() interrupt 1
{
TH0=(65536-53320)/256;
TL0=(65536-53320)%256;
if(!K2)
{
KEY_count++;
while(!K2);
if(KEY_count>=3)
{
KEY_count=0;
}
}
}
复制代码
作者:
飞云居士
时间:
2020-8-31 11:20
uchar TimeArray[8]...
上面变量定义的是无符号“字节”,计数范围是0~255.如果到0后再减1,就是255.(0xff)。所以得数不对
作者:
danq
时间:
2020-9-1 17:58
飞云居士 发表于 2020-8-31 11:20
uchar TimeArray[8]...
上面变量定义的是无符号“字节”,计数范围是0~255.如果到0后再减1,就是255.(0xf ...
感谢大佬
已解决
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1