单片机问题:单片机从ds1302时钟芯片io口读出来的数据是什么进制的,那怎么送到1602液晶显示呢?

单片机问题:单片机从ds1302时钟芯片io口读出来的数据是什么进制的,那怎么送到1602液晶显示呢?,第1张

BCD码(16进制数)。参考下面的程序(取数后送1602显示)
//向LCM中填写 年 数据
void lcm_w_yy(void){
//if(read_clock(0x8d) != yy){
yy = read_clock(0x8d);
lcm_w_test(0,0x83);
lcm_w_word("20");
lcm_w_test(0,0x84);
lcm_w_test(1,(yy/16)+0x30);
lcm_w_test(1,yy%16+0x30);
} //}
//
//向LCM中填写 月 数据
void lcm_w_mo(void){
//if(read_clock(0x89) != mo){
mo = read_clock(0x89);
lcm_w_test(0,0x90);
if(mo/16 != 0){lcm_w_test(1,(mo/16)+0x30);} //十位消隐
else{lcm_w_test(1,0x20);}//同上
lcm_w_test(1,mo%16+0x30);
lcm_w_test(0,0x91);
lcm_w_word("月");
} //}
//
//星期处理并送入LCM的指定区域
void lcm_w_xq(void){
unsigned char sel;
//if(read_clock(0x8b) != xq){
xq = read_clock(0x8b);
sel = (read_clock(0x8b))%16; //字节低4位的BCD码放入sel
lcm_w_test(0,0x97);//写入指定区域(97H 第二行第8个字)
if(sel==7) {lcm_w_word("日");} //
if(sel==6) {lcm_w_word("六");} //
if(sel==5) {lcm_w_word("五");} //
if(sel==4) {lcm_w_word("四");} //
if(sel==3) {lcm_w_test(1,0xc8);lcm_w_test(1,0xfd);} //此指令等于lcm_w_word("三"); 因为“三”的内码失效。
if(sel==2) {lcm_w_word("二");} //
if(sel==1) {lcm_w_word("一");} //星期一
lcm_w_test(0,0x95);
lcm_w_word("星期");
} //}
//
//向LCM中填写 日 数据
void lcm_w_dd(void){
// if(read_clock(0x87) != dd){
dd = read_clock(0x87);
lcm_w_test(0,0x92);
if(dd/16 != 0){lcm_w_test(1,(dd/16)+0x30);} //十位消隐
else{lcm_w_test(1,0x20);}//同上
lcm_w_test(1,dd%16+0x30);
lcm_w_test(0,0x93);
lcm_w_word("日 ");

} //}
//
//向LCM中填写 小时 数据
void lcm_w_hh(void){
if(read_clock(0x85) != hh){
hh = read_clock(0x85);
if (hh > 0x07 && hh < 0x22 && w == 0){
Beep();//整点报时音
}
}
lcm_w_test(0,0x88);
lcm_w_test(1,(hh/16)+0x30);
lcm_w_test(1,hh%16+0x30);

}
//
//向LCM中填写 分钟 数据
void lcm_w_mm(void){
if(read_clock(0x83) != mm){
mm = read_clock(0x83);
}
if(w == 0){
days();//节日显示
}
lcm_w_test(0,0x89);
lcm_w_test(1,0x3a); //":"
lcm_w_test(1,(mm/16)+0x30);
lcm_w_test(1,mm%16+0x30);
lcm_w_test(1,0x2e); //""
}
//
//刷新数据
void updata (void){
lcm_w_mm();//刷新 分
lcm_w_hh();//刷新 小时
lcm_w_dd();//刷新 日
lcm_w_xq();//更新星期值
lcm_w_mo();//刷新 月
lcm_w_yy();//刷新 年
}
//
//向LCM中填写 秒 数据
void lcm_w_ss(void){
unsigned int i=0;
unsigned char a=0,b=0,c=0;
if(read_clock(0x81) != ss){ //判断是否需要更新
ss = read_clock(0x81); //更新数据
lcm_w_test(0,0x8b); //秒值在LCM上的写入位置
lcm_w_test(1,(ss/16)+0x30); //写十位
lcm_w_test(1,ss%16+0x30); //写个位
lcm_w_word(" ");
led_b = ~led_b; //LED闪烁
updata (); //刷新数据
lcm_w_test(0,0x8d); //温度在LCM上的写入位置
i=ReadTemperature();//读温度并送显
a=i/100;
lcm_w_test(1,a+0x30); //显示温度十位
b=i/10-a10;
lcm_w_test(1,b+0x30); //个位
lcm_w_test(1,0x2e); //""
c=i-a100-b10;
lcm_w_test(1,c+0x30); //小位1位
lcm_w_word("℃"); //度C
} }

如果你是硬件做好了,出了这个问题,那你首先需要检查你的sclk和i/o有没有接反。如果这个没有问题,那么你需要着重检查下你的DS1302芯片的VCC2脚的对地电压(4脚是GND,1脚是VCC2)如果这个电压在46V以下,那么你的DS1302很可能不能正常工作,虽然在DS1302的介绍资料上这个芯片的工作电压是20~55V,但是实测发现46V以下这块芯片是无法正常工作的,我跟LZ遇到的也是相同的情况,最后使用稳压电源供给DS1302 VCC2 47V的电压以后,该芯片正常工作,调回到46以下后,又不正常了,可见这块芯片对电压的要求非常高,希望LZ能够使用正常!

如下程序 仅供参考
/
读DS1302数据函数
/
uchar read_1302(uchar DS_ADD)//读 *** 作
{
uchar DS_INF;
rst=0;
sck=0;
rst=1;
Input_1byte(DS_ADD);
DS_INF=Output_1byte();
sck=1;
rst=0;
return(DS_INF);
}
/
DS1302读数据字节子函数
/
uchar Output_1byte(void)//读一字节数据
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=sda;
sck=1;
sck=0;
}
return(ACC);
}

楼上,人家是ds1302的,呵呵,
给你个参考:
#include<reg52h>sbitclock_clk=P2^7;
sbitclock_dat=P2^6;
sbitclock_rst=P2^5;sbitwei1=P2^0;
sbitwei2=P2^1;
sbitwei3=P2^2;
sbitwei4=P2^3;
sbitwei5=P2^4;
sbitwei6=P3^3;sbita0=ACC^0;//为了编程方便定义的位变量
sbita1=ACC^1;
sbita2=ACC^2;
sbita3=ACC^3;
sbita4=ACC^4;
sbita5=ACC^5;
sbita6=ACC^6;
sbita7=ACC^7;unsignedcharTab_Num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//0-9数字voiddelay(intnum)//延时函数
{
while(num--);
}
voidclock_write(unsignedchardd)//写入一个字节,DS1302时序
{
ACC=dd;
clock_clk=0;clock_dat=a0;clock_clk=1;
clock_clk=0;clock_dat=a1;clock_clk=1;
clock_clk=0;clock_dat=a2;clock_clk=1;
clock_clk=0;clock_dat=a3;clock_clk=1;
clock_clk=0;clock_dat=a4;clock_clk=1;
clock_clk=0;clock_dat=a5;clock_clk=1;
clock_clk=0;clock_dat=a6;clock_clk=1;
clock_clk=0;clock_dat=a7;clock_clk=1;
}unsignedcharclock_read(void)//读出一个字节,时序
{clock_clk=1;clock_clk=0;a0=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a1=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a2=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a3=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a4=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a5=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a6=clock_dat;<br/><br/>clock_clk=1;clock_clk=0;a7=clock_dat;<br/><br/>return(ACC);<br/><br/>}unsignedcharread_clock(unsignedcharreg1)//从reg1寄存器读数据
{
unsignedchardd=0;
clock_clk=0;
clock_rst=0;
clock_rst=1;
clock_write(reg1);
dd=clock_read();
clock_rst=0;
return(dd);
}voidwrite_clock(unsignedcharreg2,unsignedchardate)//向reg2写入date数据
{
clock_clk=0;
clock_rst=0;
clock_rst=1;
clock_write(reg2);
clock_write(date);
clock_rst=0;
}voidshow(void)//显示和闪烁函数
{
unsignedchard,e;
unsignedinti;
for(i=0;i<1000;i++)
{
d=read_clock(0x81);//读秒
e=d;
d=d>>4;
e=e&0x0f;P0=Tab_Num[d];//秒十位
wei2=1;
delay(250);
wei2=0;
P0=Tab_Num[e];//秒各位
wei1=1;
delay(250);
wei1=0;d=read_clock(0x83);//读分钟
e=d;
d=d>>4;
e=e&0x0f;P0=Tab_Num[d];//分十位
wei4=1;
delay(250);
wei4=0;
P0=Tab_Num[e];//分各位
wei3=1;
delay(250);
wei3=0;d=read_clock(0x85);//读小时
e=d;
d=d>>4;
e=e&0x0f;P0=Tab_Num[d];//小时十位
wei6=1;
delay(250);
wei6=0;
P0=Tab_Num[e];//小时各位
wei5=1;
delay(250);
wei5=0;
}for(i=0;i<400;i++)//间隔显示
{
d=read_clock(0x87);//读日
e=d;
d=d>>4;
e=e&0x0f;
P0=Tab_Num[d];//日十位
wei2=1;
delay(250);
wei2=0;
P0=Tab_Num[e];//日各位
wei1=1;
delay(250);
wei1=0;d=read_clock(0x89);//读月
e=d;
d=d>>4;
e=e&0x0f;
P0=Tab_Num[d];//月十位
wei4=1;
delay(250);
wei4=0;
P0=Tab_Num[e];//月各位
wei3=1;
delay(250);
wei3=0;d=read_clock(0x8d);//读年
e=d;
d=d>>4;
e=e&0xf;
P0=Tab_Num[d];//年十位
wei6=1;
delay(250);
wei6=0;
P0=Tab_Num[e];//年各位
wei5=1;
delay(250);
wei5=0;
}
for(i=0;i<200;i++)//间隔显示
{
d=read_clock(0x8b);//读年
e=d;
d=d>>4;
e=e&0xf;
P0=Tab_Num[d];//年十位
wei2=1;
delay(250);
wei2=0;
P0=Tab_Num[e];//年各位
wei1=1;
delay(250);
wei1=0;
}
}/--------------------时钟的初始化---------------------------/
voidInit_1302(void)//如果不满意现在的表,可以初始化调整,写入程序之后,再把初始化屏蔽掉
{
write_clock(0x8e,0x00);//close_protect
delay(250);
write_clock(0x8c,0x08);//year08年
delay(250);
write_clock(0x88,0x6);//month06
delay(250);
write_clock(0x86,0x25);//date25
delay(250);
write_clock(0x84,0x8);//hour8
delay(250);
write_clock(0x82,0x28);//minute28
delay(250);
write_clock(0x80,0x29);//second40
delay(250);
write_clock(0x8a,0x03);//week_day3
delay(250);
write_clock(0x90,0xa0);//supply_power
delay(250);write_clock(0x8e,0x80);//protect
delay(250);
}
voidmain(void)
{
inti;
for(i=0;i<2;i++)
delay(2000);
Init_1302();//DS1302寄存器初始化P2=0x00;while(1)
{
show();
}
}

读的时候:
SCK=1;//时钟拉高
if(SDA)//判断数据线上是0还是1
temp|=0x80; //保存数据1 是0的话不管,右移时自动补的就是0
SCK=0;//时钟拉低
这显然是上升沿读数据呀。

这里给你一个我自己的proteus亲自调试通过的程序,若要求全部调试程序请发站内信,uchar du(uchar addr) / 读芯片返回一个字节十进制的数据 /
{
uchar i;
uchar dd,du,du1,du2;
dsres=0;
dssclk=0;
dsres=1;
for(i = 0; i < 8; i++)
{
dssclk=0;
dsio=0;
if(addr & 0x01)
dsio= 1;
dssclk = 1;
addr >>= 1;
}---------以上发送一个字节地址

dsio=1; -----ds1302通信io口
for(i = 0; i < 8; i++)
{
ACC=ACC>>1;
dssclk=0;
if(dsio==0)
ACC_7=0;
else
ACC_7=1;
dssclk=1;
}--------------以上读取一个字节数据
dsres=0;
dd=ACC;
du1=dd/16;
du2=dd%16;
du=du110+du2;---------以上进行十六进制到十进制转化
return du;
}
你的程序我大致看了,问题主要有二个,你的时序可能还没弄清楚,要严格按照时序,具体的资料你手头应该也有,读写数据的时候你都应该按照上升沿进行数据传输,第二个问题就51在作为通信口读数据的问题了,一定要记住51作为数据通信口的时候一定要先拉高端口电平也就是我上面注释的dsio=1;为什么这样做具体你可以查阅51io口的结构图,vcc接上拉电阻再接一个mos管,电阻和mos管之间是io口,只有端口写1的时候,mos管工作在截至状态,此时读引脚和vcc连接,这时候若io是高电平则直接读出高电平1,若io口是低电平则外部芯片的吸电把端口电平拉低,读引脚读出低电平0,要区分读引脚和读端口寄存器的区别!还有其他问题的话 站内信 呵呵 ,望你能弄懂最后别忘了给分 谢谢 !!!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/13181526.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-06-17
下一篇 2023-06-17

发表评论

登录后才能评论

评论列表(0条)

保存