51单片机+ds1302出现乱码,求助?
时间:10-02
整理:3721RD
点击:
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define qw P1
uchar code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x84,0x0E};// 显示段码值
uchar home[]={12,20,0}; //时分秒
uchar write_add[]={0x84,0x82,0x80};//时 分 秒 写寄存器地址
uchar read_add[]={0x85,0x83,0x81}; //时 分 秒 读寄存器地址
uchar disp[6];
uchar wei[]={0,1,2,3,4,5,6,7,};
uchar flng=0;//初始化标志位
sbit SCLK = P1^6; //实时时钟时钟线引脚
sbit SDA = P1^7; //实时时钟数据线引脚
sbit RST = P1^5; //实时时钟复位线引脚
void delayus(uchar a) //延迟
{
uchar i,j;
for(i=0;i<a;i++)
for(j=0;j<110;j++);
}
/************************************************
*名称: DS1302WriteByte
*说明: 无
*功能: 写入8bit数据
*调用: delayus()
*输入: dat:要写入的数据
*输出: 无
*************************************************/
void DS1302WriteByte(uchar dat)
{
uchar i;
SCLK=0;//初始时钟线置为0
delayus(2);
for(i=0;i<8;i++)//开始传输8个字节的数据
{
SDA=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的
delayus(2);
SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输
delayus(2);
SCLK=0;//时钟线拉低,为下一个上升沿做准备
dat>>=1;//数据右移一位,准备传输下一位数据
}
}
void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据
{
RST=0; delayus(2);
SCLK=0; delayus(2);
RST=1; delayus(2);
DS1302WriteByte(add); //传地址
DS1302WriteByte(dat); //传数据
RST=0; delayus(2);
SDA=1;
SCLK=1;
}
/************************************************
*名称: DS1302ReadByte()
*说明: 无
*功能: 读取8bit的数据
*调用: delayus()
*输入: 无
*输出: dat:读取的数据
*************************************************/
uchar DS1302ReadByte()
{
uchar i,dat;
delayus(2);
for(i=0;i<8;i++)
{
dat>>=1;//要返回的数据左移一位
if(SDA==1)//当数据线为高时,证明该位数据为1
dat|=0x80;//要传输数据的当前值置为1,若不是,则为0
SCLK=1;//拉高时钟线
delayus(2);
SCLK=0;//制造下降沿
delayus(2);
}
return dat;//返回读取出的数据
}
/************************************************
*名称: uchar DS1302Read()
*说明: 先写地址,后读数据
*功能: 从cmd相应地址中读取一个字节的数据
*调用: DS1302WriteByte(),DS1302ReadByte()
*输入: cmd:要写入的控制字节
*输出: dat:读取的数据
*************************************************/
uchar DS1302Read(uchar cmd)
{
uchar dat;
RST=0;//初始CE线置为0
SCLK=0;//初始时钟线置为0
RST=1;//初始CE置为1,传输开始
DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址
dat=DS1302ReadByte();//读取要得到的时间/日期
SCLK=1;//时钟线拉高
RST=0;//读取结束,CE置为0,结束数据的传输
return dat;//返回得到的时间/日期
}
void ds1302_init() //1302芯片初始化子函数(,12:20:00,)
{
uchar i,j;
for(i=0;i<3;i++)
{
j=home[i]/10;
home[i]=home[i]%10;
home[i]=home[i]+j*16 ;
}
write_1302(0x8e,0x00); //允许写,禁止写保护
for(i=0;i<3;i++)
{
write_1302(write_add[i],home[i]);
delayus(2);
}
write_1302(0x8e,0x80); //打开写保护
flng=1;
}
void read() //读时钟
{
uchar i;
for(i=0;i<3;i++)
{
home[i]= DS1302Read(read_add[i]);
delayus(2);
}
disp[0]=home[0]/16;
disp[1]=home[0]%16;
disp[2]=home[1]/16;
disp[3]=home[1]%16;
disp[4]=home[2]/16;
disp[5]=home[2]%16;
}
void display()
{ uchar i;
for(i=0;i<7;i++)
{
P2=tab[disp[i]];
delayus(2);
qw=wei[i];
}
}
main()
{
if(!flng)
{
ds1302_init();
}
while(1)
{
read();
display() ;
}
}
#define uint unsigned int
#define uchar unsigned char
#define qw P1
uchar code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x84,0x0E};// 显示段码值
uchar home[]={12,20,0}; //时分秒
uchar write_add[]={0x84,0x82,0x80};//时 分 秒 写寄存器地址
uchar read_add[]={0x85,0x83,0x81}; //时 分 秒 读寄存器地址
uchar disp[6];
uchar wei[]={0,1,2,3,4,5,6,7,};
uchar flng=0;//初始化标志位
sbit SCLK = P1^6; //实时时钟时钟线引脚
sbit SDA = P1^7; //实时时钟数据线引脚
sbit RST = P1^5; //实时时钟复位线引脚
void delayus(uchar a) //延迟
{
uchar i,j;
for(i=0;i<a;i++)
for(j=0;j<110;j++);
}
/************************************************
*名称: DS1302WriteByte
*说明: 无
*功能: 写入8bit数据
*调用: delayus()
*输入: dat:要写入的数据
*输出: 无
*************************************************/
void DS1302WriteByte(uchar dat)
{
uchar i;
SCLK=0;//初始时钟线置为0
delayus(2);
for(i=0;i<8;i++)//开始传输8个字节的数据
{
SDA=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的
delayus(2);
SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输
delayus(2);
SCLK=0;//时钟线拉低,为下一个上升沿做准备
dat>>=1;//数据右移一位,准备传输下一位数据
}
}
void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据
{
RST=0; delayus(2);
SCLK=0; delayus(2);
RST=1; delayus(2);
DS1302WriteByte(add); //传地址
DS1302WriteByte(dat); //传数据
RST=0; delayus(2);
SDA=1;
SCLK=1;
}
/************************************************
*名称: DS1302ReadByte()
*说明: 无
*功能: 读取8bit的数据
*调用: delayus()
*输入: 无
*输出: dat:读取的数据
*************************************************/
uchar DS1302ReadByte()
{
uchar i,dat;
delayus(2);
for(i=0;i<8;i++)
{
dat>>=1;//要返回的数据左移一位
if(SDA==1)//当数据线为高时,证明该位数据为1
dat|=0x80;//要传输数据的当前值置为1,若不是,则为0
SCLK=1;//拉高时钟线
delayus(2);
SCLK=0;//制造下降沿
delayus(2);
}
return dat;//返回读取出的数据
}
/************************************************
*名称: uchar DS1302Read()
*说明: 先写地址,后读数据
*功能: 从cmd相应地址中读取一个字节的数据
*调用: DS1302WriteByte(),DS1302ReadByte()
*输入: cmd:要写入的控制字节
*输出: dat:读取的数据
*************************************************/
uchar DS1302Read(uchar cmd)
{
uchar dat;
RST=0;//初始CE线置为0
SCLK=0;//初始时钟线置为0
RST=1;//初始CE置为1,传输开始
DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址
dat=DS1302ReadByte();//读取要得到的时间/日期
SCLK=1;//时钟线拉高
RST=0;//读取结束,CE置为0,结束数据的传输
return dat;//返回得到的时间/日期
}
void ds1302_init() //1302芯片初始化子函数(,12:20:00,)
{
uchar i,j;
for(i=0;i<3;i++)
{
j=home[i]/10;
home[i]=home[i]%10;
home[i]=home[i]+j*16 ;
}
write_1302(0x8e,0x00); //允许写,禁止写保护
for(i=0;i<3;i++)
{
write_1302(write_add[i],home[i]);
delayus(2);
}
write_1302(0x8e,0x80); //打开写保护
flng=1;
}
void read() //读时钟
{
uchar i;
for(i=0;i<3;i++)
{
home[i]= DS1302Read(read_add[i]);
delayus(2);
}
disp[0]=home[0]/16;
disp[1]=home[0]%16;
disp[2]=home[1]/16;
disp[3]=home[1]%16;
disp[4]=home[2]/16;
disp[5]=home[2]%16;
}
void display()
{ uchar i;
for(i=0;i<7;i++)
{
P2=tab[disp[i]];
delayus(2);
qw=wei[i];
}
}
main()
{
if(!flng)
{
ds1302_init();
}
while(1)
{
read();
display() ;
}
}
你看看你Proteus中用的数码管与你的数码管显示的代码是否一致?
共阴 or 共阳;
Proteus中用的是共阳啊,是不是程序出问题了?
图像不全不清,难以判断,数码管的段位审定如何?建议输入标准程序仿真,如全写入0~8,在判断,即先硬件在软件。
是的!你可以你简单地写个Demo 程序,排除硬件问题!
之后再看软件!因为贴图,模糊,看不清!
其实你用Proteus仿真,目前IO也没有那么紧张,位选端可以直接占用
整个P1口!没有必要用串----并IC!
谢谢各位,已经搞定了
时钟—ds1302+数码管显示
http://bbs.elecfans.com/forum.ph ... &fromuid=748670