如何读出DS1302里面的时钟数据?

将年月日时分秒分别读出,请给出C51语句!... 将年月日时分秒分别读出,请给出C51语句! 展开
 我来答
sdq0682116
2011-03-03
知道答主
回答量:6
采纳率:0%
帮助的人:9376
展开全部
#include <REG51.H>
#include <intrins.h>
//#include "LCD1602.h"
//#include "DS1302.h"
#define uint unsigned int
#define uchar unsigned char
sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚
sbit DS1302_IO = P1^6; //实时时钟数据线引脚
sbit DS1302_RST = P1^5; //实时时钟复位线引脚
sbit wireless_1 = P3^0;
sbit wireless_2 = P3^1;
sbit wireless_3 = P3^2;
sbit wireless_4 = P3^3;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
sbit Set = P2^0; //模式切换键
sbit Up = P2^1; //加法按钮
sbit Down = P2^2; //减法按钮
sbit out = P2^3; //立刻跳出调整模式按钮
char done,count,temp,flag,up_flag,down_flag;
uchar TempBuffer[5],week_value[2];

/***********DS1302时钟部分子程序******************/
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;

#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C

void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}

unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}

void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}

void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}

void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4] = '/';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7] = '/';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';

Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}

void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
}
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->DateString[8] = '\0';
}

void Initial_DS1302(void) //时钟芯片初始化
{
unsigned char Second="Read1302"(DS1302_SECOND);
if(Second&0x80) //判断时钟芯片是否关闭
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
Write1302(0x88,0x07);
Write1302(0x86,0x25);
Write1302(0x8a,0x07);
Write1302(0x84,0x23);
Write1302(0x82,0x59);
Write1302(0x80,0x55);
Write1302(0x8e,0x80); //禁止写入
}

}

void Upkey()//升序按键
{
Up=1;
if(Up==0||wireless_2==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //读取秒数
temp="temp"+1; //秒数加1
up_flag=1; //数据调整后更新标志
if((temp&0x7f)>0x59) //超过59秒,清零
temp="0";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //读取分数
temp="temp"+1; //分数加1
up_flag=1;
if(temp>0x59) //超过59分,清零
temp="0";
break;
case 3:
temp="Read1302"(DS1302_HOUR); //读取小时数
temp="temp"+1; //小时数加1
up_flag=1;
if(temp>0x23) //超过23小时,清零
temp="0";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //读取星期数
temp="temp"+1; //星期数加1
up_flag=1;
if(temp>0x7)
temp="1";
break;
case 5:
temp="Read1302"(DS1302_DAY); //读取日数
temp="temp"+1; //日数加1
up_flag=1;
if(temp>0x31)
temp="1";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //读取月数
temp="temp"+1; //月数加1
up_flag=1;
if(temp>0x12)
temp="1";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //读取年数
temp="temp"+1; //年数加1
up_flag=1;
if(temp>0x85)
temp="0";
break;
default:break;
}

while(Up==0);
while(wireless_2==1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Downkey()//降序按键
{
Down=1;
if(Down==0||wireless_3==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //读取秒数
temp="temp-1"; //秒数减1
down_flag=1; //数据调整后更新标志
if(temp==0x7f) //小于0秒,返回59秒
temp="0x59";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //读取分数
temp="temp-1"; //分数减1
down_flag=1;
if(temp==-1)
temp="0x59"; //小于0秒,返回59秒
break;
case 3:
temp="Read1302"(DS1302_HOUR); //读取小时数
temp="temp-1"; //小时数减1
down_flag=1;
if(temp==-1)
temp="0x23";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //读取星期数
temp="temp-1"; //星期数减1
down_flag=1;
if(temp==0)
temp="0x7";;
break;
case 5:
temp="Read1302"(DS1302_DAY); //读取日数
temp="temp-1"; //日数减1
down_flag=1;
if(temp==0)
temp="31";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //读取月数
temp="temp-1"; //月数减1
down_flag=1;
if(temp==0)
temp="12";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //读取年数
temp="temp-1"; //年数减1
down_flag=1;
if(temp==-1)
temp="0x85";
break;
default:break;
}

while(Down==0);
while(wireless_3==1);
}
}

void Setkey()//模式选择按键
{
Set=1;
if(Set==0||wireless_4==1)
{
mdelay(8);
count="count"+1; //Setkey按一次,count就加1
done="1"; //进入调整模式
while(Set==0);
while(wireless_4==1);
}

}

void keydone()//按键功能执行
{ uchar Second;
if(flag==0) //关闭时钟,停止计时
{ Write1302(0x8e,0x00); //写入允许
temp="Read1302"(0x80);
Write1302(0x80,temp|0x80);
Write1302(0x8e,0x80); //禁止写入
flag="1";
}
Setkey(); //扫描模式切换按键
switch(count)
{case 1:do //count=1,调整秒
{
outkey(); //扫描跳出按钮
Upkey(); //扫描加按钮
Downkey(); //扫描减按钮
if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,temp|0x80); //写入新的秒数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}

hide_sec++; //位闪计数
if(hide_sec>3)
hide_sec=0;
show_time(); //液晶显示数据
}while(count==2);break;
case 2:do //count=2,调整分
{
hide_sec=0;
outkey();
Upkey();
Downkey();
if(temp>0x60)
temp="0";
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x82,temp); //写入新的分数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_min++;
if(hide_min>3)
hide_min=0;
show_time();
}while(count==3);break;
case 3:do //count=3,调整小时
{
hide_min=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x84,temp); //写入新的小时数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_hour++;
if(hide_hour>3)
hide_hour=0;
show_time();
}while(count==4);break;
case 4:do //count=4,调整星期
{
hide_hour=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8a,temp); //写入新的星期数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_week++;
if(hide_week>3)
hide_week=0;
show_time();
}while(count==5);break;
case 5:do //count=5,调整日
{
hide_week=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x86,temp); //写入新的日数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_day++;
if(hide_day>3)
hide_day=0;
show_time();
}while(count==6);break;
case 6:do //count=6,调整月
{
hide_day=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x88,temp); //写入新的月数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_month++;
if(hide_month>3)
hide_month=0;
show_time();
}while(count==7);break;
case 7:do //count=7,调整年
{
hide_month=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,temp); //写入新的年数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_year++;
if(hide_year>3)
hide_year=0;
show_time();
}while(count==8);break;
case 8: count="0";hide_year=0; //count8, 跳出调整模式,返回默认显示状态
Second="Read1302"(DS1302_SECOND);
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止写入
done="0";
break; //count=7,开启中断,标志位置0并退出
default:break;

}

}
ZESTRON
2024-09-04 广告
在Dr. O.K. Wack Chemie GmbH,我们高度重视ZESTRON的表界面分析技术。该技术通过深入研究材料表面与界面的性质,为提升产品质量与可靠性提供了有力支持。ZESTRON的表界面分析不仅涵盖了相变化、化学反应、吸附与解吸... 点击进入详情页
本回答由ZESTRON提供
wangtk1982
推荐于2016-08-10 · TA获得超过3742个赞
知道大有可为答主
回答量:3206
采纳率:100%
帮助的人:1452万
展开全部
一个例子 重点看DS1302_Read()

#include <reg51.h>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define SECOND 0x81
#define MINUTE 0x83
#define HOUR 0x85
sbit rs=P2^0;
sbit rw=P2^1;
sbit ep=P2^2;
sbit DS1302_SCLK = P1^0;
sbit DS1302_IO= P1^1;
sbit DS1302_RST = P1^2;
sbit M=P3^2;
sbit U=P3^3;
sbit D=P3^4;
unsigned char sel=0;
uchar code DIS1[]={“abcdef"};
uchar code DIS2[]={"abcdef"};
/////////////////////////延时////////////////////////////////
void delay(uint ms)
{
unsigned int a,b;
for(a=0;a<ms;a++)
for(b=0;b<120;b++);
}
////////////////////////////////////////////////////////////
/***************DS1302驱动************************/
////////////////////////////////////////////////////////////
void DS1302_Write(uchar D)
{
uchar i;
for(i=0;i<8;i++)
{
DS1302_IO=D&0x01;
DS1302_SCLK=1;
DS1302_SCLK=0;
D=D>>1;
}
}
////////////////////////////////////////////////////////////
uchar DS1302_Read()
{
uchar TempDat=0,i;
for(i=0;i<8;i++)
{
TempDat>>=1;
if(DS1302_IO) TempDat=TempDat|0x80;
DS1302_SCLK=1;
DS1302_SCLK=0;

}
return TempDat;
}
////////////////////////////////////////////////////////////
void WDS1302(uchar ucAddr, uchar ucDat)
{
DS1302_RST = 0;
DS1302_SCLK = 0;
DS1302_RST = 1;
DS1302_Write(ucAddr);
DS1302_Write(ucDat);
DS1302_SCLK = 1;
DS1302_RST = 0;
}
////////////////////////////////////////////////////////////
uchar RDS1302(uchar ucAddr)
{
uchar ucDat;
DS1302_RST = 0;
DS1302_SCLK = 0;
DS1302_RST = 1;
DS1302_Write(ucAddr);
ucDat=DS1302_Read();
DS1302_SCLK = 1;
DS1302_RST = 0;
return ucDat;
}
//////////////////////////////////////////////////////////
void init_1302()
{
WDS1302(0x8e,0x00);//开保护寄存器
WDS1302(0x80,0x55);//秒
WDS1302(0x82,0x59);//分
WDS1302(0x84,0x23);//时
WDS1302(0x8A,0x07);//星期
WDS1302(0x86,0x02);//日
WDS1302(0x88,0x08);//月
WDS1302(0x8C,0x09);//年
WDS1302(0x90,0xab);//卷电流充电
WDS1302(0x8e,0x80);//关保护寄存器
}

//////////////////////////////////////////////////////////
/************************1602驱动************************/
//////////////////////////////////////////////////////////

bit lcd_bz()
{
bit result;
rs = 0;
rw = 1;
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0 & 0x80);
ep = 0;
return result;
}
////////////////////////////////////////////////////////
void lcd_wcmd(unsigned char cmd)
{
while(lcd_bz());
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep= 0;
}
/////////////////////////////////////////////////////////
void lcd_pos(unsigned char pos)
{
lcd_wcmd(pos | 0x80);
}
/////////////////////////////////////////////////////////
void lcd_wdat(unsigned char dat)
{
while(lcd_bz());
rs = 1;
rw = 0;
ep = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//////////////////////////////////////////////////////////
void lcd_init()
{
lcd_wcmd(0x38);
delay(1);
lcd_wcmd(0x0c);
delay(1);
lcd_wcmd(0x06);
delay(1);
lcd_wcmd(0x01);
delay(1);
}

/////////////////////////////////////////////////////////
/*********************调时函数*************************/
/////////////////////////////////////////////////////////
void set_time()
{

signed char address,item;
signed char max,mini;
if(M==0)
{
sel++;
delay(300);
if(sel==6) sel=0;
if(sel==2) {address=0x82; max=59;mini=0; }
if(sel==1) {address=0x84; max=23;mini=0; }
if(sel==3) {address=0x8c; max=99;mini=9;}
if(sel==4) {address=0x88; max=12;mini=1; }
if(sel==5) {address=0x86; max=31;mini=1; }
M=1;
}
item=((RDS1302(address+1))/16)*10 + (RDS1302(address+1))%16;
if(U == 0)
{
delay(200);
U=1;
item++;
}
if(D == 0)
{
delay(200);
D=1;
item--;
}
if(item>max) item=mini;
if(item<mini) item=max;
WDS1302(0x8e,0x00);//允许写操作
WDS1302(address,(item/10)*16+item%10);
WDS1302(0x8e,0x80);//写保护,禁止写操作
}
/////////////////////////////////////////////////////////
/*********************显示子函数************************/
/////////////////////////////////////////////////////////
uchar lcdshow_u(uchar i,uchar y)
{

lcd_wcmd(0x80+0x00+i);
lcd_wdat(y);

}

uchar lcdshow_d(uchar i,uchar y)
{
lcd_wcmd(0x80+0x40+i);
lcd_wdat(y);
}
/////////////////////////////////////////////////////////
/*******************显示函数****************************/
/////////////////////////////////////////////////////////
void display(void)
{

uchar x,y;

x=RDS1302(HOUR);
y=x;
x=x>>4; lcdshow_u(6,0x30+x);
y=y&0x0f; lcdshow_u(7,0x30+y);
lcdshow_u(8,':');

x=RDS1302(MINUTE);
y=x;
x=x>>4; lcdshow_u(9,0x30+x);
y=y&0x0f; lcdshow_u(0x0a,0x30+y);
lcdshow_u(0x0b,':');
x=RDS1302(SECOND);
y=x;
x=x>>4; lcdshow_u(0x0c,0x30+x);
y=y&0x0f; lcdshow_u(0x0d,0x30+y);

x=RDS1302(0x8d);
y=x;
x=x>>4; lcdshow_d(8,0x30+x);
y=y&0x0f; lcdshow_d(9,0x30+y);
lcdshow_d(0x0a,'-');
x=RDS1302(0x89);
y=x;
x=x>>4; lcdshow_d(0x0b,0x30+x);
y=y&0x0f; lcdshow_d(0x0c,0x30+y);
lcdshow_d(0x0d,'-');
x=RDS1302(0x87);
y=x;
x=x>>4; lcdshow_d(0x0e,0x30+x);
y=y&0x0f; lcdshow_d(0x0f,0x30+y);
for(x=45;x>0;x--)
{
set_time();
delay(10);
}
}
////////////////////////////////////////////////////////////////
/**************************主函数******************************/
////////////////////////////////////////////////////////////////
void main()
{
uchar i;
lcd_init();
delay(10);
lcd_pos(0x03);
i = 0;
while(DIS1[i] != '\0')
{
lcd_wdat(DIS1[i]);
i++;
}
lcd_pos(0x42);
i = 0;
while(DIS2[i] != '\0')
{
lcd_wdat(DIS2[i]);
i++;
}

//init_1302();
delay(1000);
for(i=0;i<17;i++)
{
lcdshow_u(i,'>');
delay(90) ;
}
for(i=0;i<17;i++)
{
lcdshow_d(i,'>');
delay(90) ;
}
lcd_init();
delay(10);
lcdshow_u(0,'T');
lcdshow_u(1,'i');
lcdshow_u(2,'m');
lcdshow_u(3,'e');

lcdshow_d(0,'D');
lcdshow_d(1,'a');
lcdshow_d(2,'t');
lcdshow_d(3,'a');

lcdshow_d(6,'2');
lcdshow_d(7,'0'); //LCD框架描绘

while(1)
{
set_time();
if(sel==2) {lcdshow_u(9,' ');lcdshow_u(0x0a,' ');delay(500); }
if(sel==1) {lcdshow_u(6,' ');lcdshow_u(7,' ');delay(500); }
if(sel==4) {lcdshow_d(0x0b,' ');lcdshow_d(0x0c,' ');delay(500); }
if(sel==5) {lcdshow_d(0x0e,' ');lcdshow_d(0x0f,' ');delay(500); } //调时LCD闪烁显示
display();
}

}
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
手机用户52955
2011-03-05 · 超过35用户采纳过TA的回答
知道答主
回答量:178
采纳率:0%
帮助的人:0
展开全部
P1.2;令=0

DS_READ�SETBP1.2;令=0。

CLRP1.1;令SCLK=0。

CLRP1.2;令=1,启动芯片。

LCALLDS_WSUB;写8位地址。

LCALLDS_RSUB;读出8位数据。

RET

DS_WSUB�MOVR7,#08H

WL00P�RRCA;A为地址字节。

MOVP1.0,C

SETBP1.1;在时钟上升沿

NOP;输入地址字节。

CLRP1.1

DJNZR7�WL00P

RET

DS_RSUB�SETBP1.0;为读数据作准备。

MOVR7�#08H

RL00P:SETBP1.1

NOP

CLRP1.1;在第9个正脉冲的下

MOVC,P1.0;降沿开始输出数据。

RRCA;A中为读出的数据。

DJNZR7,RL00P

RET

若使用如下程序对DSl302的RAM1�其内容为5AH 进行读操作

READ:MOVA�#11000101B;RAM1单元的读地址。

LCAllDS_READ;调用读子程序。

则程序执行后A中的数据为2DH,显然读出的数据不正确。若再使用一条RLA指令调整后,则A中为5AH,结果才正确。由此说明:使用上述程序读出的RAM1单元中的第0位数据实为第1位数据,读出的第7位数据实为第0位数据。

经笔者仔细研究时序图和多次试验得知,问题的原因在于:对于读操作时序,在SCLK出现第8个正脉冲时,上升沿输入地址字节的最后一位数据,而在此正脉冲的下降沿就要输出数据字节的第0位数据。然而笔者的程序中是在第9个正脉冲的下降沿才误认为输出了数据字节的第0位数据,此位数据事实上是第二个下降沿输出的,故实为数据字节的第1位数据。经笔者实验:只要RST保持为高电平,如果超过8个下降沿,它们将重新从第0位输出数据位,因程序中输出的最后一位数据位,是9个下降沿输出的数据位,故实为数据字节的第0位数据位。

由此可见,单字节读操作的时序图如改为图2所示时序图,则读者较容易理解可避免发生上述编程错误。

只要将上述的DS_RSUB子程序改为如下的子程序即可解决上述问题:

DS_RSUBl:SETBP1.0;为读数据作准备

MOVR7,#08H

RL00P:CLRP1.1;SCLK第8个正脉冲的

MOVC,P1.0;下降沿开始输出数据。

RAC

SETBP1.1

DJNZR7,RL00P

RET
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式