新人的血和泪~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

jj89816657 2011-08-13 08:08:21
不知不觉学习C51已经2个多月了,今天下午心血来潮打算写一个DS18B20的温度计来玩玩,希望检验下自己,结果悲剧啊,琢磨了一下时序图,单总线的,完全不懂,磕磕碰碰的挤了程序出来,居然完全没反应,好吧,我也觉得自己太自大了,才学习2个月就想自己看时序图自己写,然后,我自己参考源码,还是有些地方弄不懂~~
比如i=i&(~((0X01)<<(num))); 这样一个语句,怎么也看不懂~太伤人了,自尊心也被狠狠的抽了一耳光~~
...全文
171 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoyucong 2011-08-15
  • 打赏
  • 举报
回复
lz 下面这个给你做参考51的,是我好早在学完51后编的综合项,一个用ds1302,ds18b20在LCD1602上显示的按键可调万年历,其中计算器应该没加上去,可以借鉴下的,没什么注释但应该易懂的/.

#include <reg52.h>
sbit DS_CLK=P1^3;
sbit DS_IO=P1^2;
sbit DS_CE=P1^1;
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
sbit DQ=P2^7;
sbit busy_bit=P0^7;
sbit gn=P3^6;
sbit jia=P3^4;
sbit jian=P3^2;
bit flag;
unsigned char miao=0,fen=0x23,xshi=0x17,nian=0x11,yue=0x05,ri=0x19,xing=4;

void delay_lcd(unsigned int t)
{
unsigned char i;
while(t--)
for(i=0;i<115;i++);
}
void busy()
{
bit temp;
P0=0xff;
RS=0;
RW=1;
do
{
E=1;
temp=busy_bit;
E=0;
}while(temp);
}
void write_lcd(bit bf,bit dat_cmd,unsigned char content)
{
if(bf)busy();
if(dat_cmd)
{
RS=1;
RW=0;
}
else
{
RS=0;
RW=0;
}
E=1;
P0=content;
E=0;
}
void init_lcd()
{
delay_lcd(15);
write_lcd(0,0,0x38);
delay_lcd(5);
write_lcd(0,0,0x38);
delay_lcd(5);
write_lcd(0,0,0x38);
write_lcd(1,0,0x38);
write_lcd(1,0,0x08);
write_lcd(1,0,0x01);
write_lcd(1,0,0x06);
write_lcd(1,0,0x0c);
}
void write_1302(unsigned char cmd,unsigned char dat)
{
unsigned char i;
DS_CLK=0;
DS_CE=0;
DS_CE=1;
for(i=0;i<8;i++)
{
DS_IO=cmd&1;
DS_CLK=0;
DS_CLK=1;
cmd>>=1;
}
for(i=0;i<8;i++)
{
DS_IO=dat&1;
DS_CLK=0;
DS_CLK=1;
dat>>=1;
}
}
unsigned char read_1302(unsigned char cmd)
{
unsigned char i,dat=0;
DS_CLK=0;
DS_CE=0;
DS_CE=1;
for(i=0;i<8;i++)
{
DS_IO=cmd&1;
DS_CLK=0;
DS_CLK=1;
cmd>>=1;
}
for(i=0;i<8;i++)
{
DS_CLK=1;
DS_CLK=0;
dat>>=1;
if(DS_IO)dat|=0x80;
}
dat=dat/16*10+dat%16;
return dat;
}




void init_1302()
{
write_1302(0x8e,0x00);
write_1302(0x84,xshi);
write_1302(0x82,fen);
write_1302(0x80,miao);
write_1302(0x8c,nian);
write_1302(0x88,yue);
write_1302(0x86,ri);
write_1302(0x8a,xing);
write_1302(0x8e,0x80);
}

/**************************************************************
ds18b20
**************************************************************/
void delay(unsigned int t)
{
while(t--);
}
void init_ds18b20()
{
DQ=0;
delay(100);
DQ=1;
delay(4);
while(DQ);
while(~DQ)
delay(4);
}
void write(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&1;
delay(8);
DQ=1;
dat>>=1;
}
}
unsigned int read()
{
unsigned char i;
unsigned int dat=0;
for(i=0;i<16;i++)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)dat|=0x8000;
delay(8);
}
return(dat);
}
unsigned int read_temp() //温度转换及读取
{
unsigned int temp;
init_ds18b20(); //产生脉冲
write(0xcc); //跳过ROM
write(0x44); //温度转换
init_ds18b20();
write(0xcc);
write(0xbe); //读存储器
temp=read(); //读温度值
return(temp);
}
/***********************************************************/
void init2()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
/*****************************************************/
void gnmod() //功能模块
{

unsigned char an1;
if(gn==0)
{
delay(5);
if(gn==0)
{

while(!gn);

TR0=0;

an1++;
if(an1==1)
{
write_lcd(1,0,0xcd);
write_lcd(1,0,0x0f);
}
if(an1==2) write_lcd(1,0,0xcb);
if(an1==3) write_lcd(1,0,0xc8);
if(an1==4) write_lcd(1,0,0xc5);
if(an1==5) write_lcd(1,0,0x89);
if(an1==6) write_lcd(1,0,0x86);
if(an1==7) write_lcd(1,0,0x83);
if(an1==8)
{
TR0=1;
write_lcd(1,0,0x0c);
an1=0;
}
}
}
if(jia==0)
{ //P2=0x00;
//P0=0xf0; 是否进入加
delay(5);
if(jia==0)
{
while(!jia);
write_1302(0x8e,0x00);
switch(an1)
{

case 1:xing++;if(xing==8)xing=1;
write_1302(0x8a,xing);
write_lcd(1,0,0xcd);
write_lcd(1,1,read_1302(0x8b)%10+'0');
write_lcd(1,0,0xcd); break;
case 2:miao=miao/16*10+miao%16;
miao++;if(miao==60)miao=0;
miao=miao/10*16+miao%10;
write_1302(0x80,miao);
write_lcd(1,0,0xca);
write_lcd(1,1,read_1302(0x81)/10+'0');
write_lcd(1,1,read_1302(0x81)%10+'0');
write_lcd(1,0,0xcb); break;
case 3: fen=fen/16*10+fen%16;
fen++;if(fen==60)fen=0;
fen=fen/10*16+fen%10;
write_1302(0x82,fen);
write_lcd(1,0,0xc7);
write_lcd(1,1,read_1302(0x83)/10+'0');
write_lcd(1,1,read_1302(0x83)%10+'0');
write_lcd(1,0,0xc8);break;
case 4: xshi=xshi/16*10+xshi%16;
xshi++;if(xshi==24)xshi=0;
xshi=xshi/10*16+xshi%10;
write_1302(0x84,xshi);
write_lcd(1,0,0xc4);
write_lcd(1,1,read_1302(0x85)/10+'0');
write_lcd(1,1,read_1302(0x85)%10+'0');
write_lcd(1,0,0xc5); break;
case 5: ri=ri/16*10+ri%16;
ri++;if(ri==32)ri=1;
ri=ri/10*16+ri%10;
write_1302(0x86,ri);
write_lcd(1,0,0x88);
write_lcd(1,1,read_1302(0x87)/10+'0');
write_lcd(1,1,read_1302(0x87)%10+'0');
write_lcd(1,0,0x89); break;
case 6: yue=yue/16*10+yue%16;
yue++;if(yue==13)yue=1;
yue=yue/10*16+yue%10;
write_1302(0x88,yue);
write_lcd(1,0,0x85);
write_lcd(1,1,read_1302(0x89)/10+'0');
write_lcd(1,1,read_1302(0x89)%10+'0');
write_lcd(1,0,0x86); break;
case 7:nian=nian/16*10+nian%16;
nian++;if(nian==100)nian=0;
nian=nian/10*16+nian%10;
write_1302(0x8c,nian);
write_lcd(1,0,0x82);
write_lcd(1,1,read_1302(0x8d)/10+'0');
write_lcd(1,1,read_1302(0x8d)%10+'0');
write_lcd(1,0,0x83); break;
}
write_1302(0x8e,0x80);

}
}

if(jian==0)
{
delay(5);
if(jian==0)
{
while(!jian);
write_1302(0x8e,0x00);
switch(an1)
{

case 1:xing--;if(xing==0)xing=7;
write_1302(0x8a,xing);
write_lcd(1,0,0xcd);
write_lcd(1,1,read_1302(0x8b)%10+'0');
write_lcd(1,0,0xcd); break;
case 2:miao=miao/16*10+miao%16;
miao--;if(miao==-1)miao=59;
miao=miao/10*16+miao%10;
write_1302(0x80,miao);
write_lcd(1,0,0xca);
write_lcd(1,1,read_1302(0x81)/10+'0');
write_lcd(1,1,read_1302(0x81)%10+'0');
write_lcd(1,0,0xcb); break;
case 3: fen=fen/16*10+fen%16;
fen--;if(fen==0)fen=59;
fen=fen/10*16+fen%10;
write_1302(0x82,fen);
write_lcd(1,0,0xc7);
write_lcd(1,1,read_1302(0x83)/10+'0');
write_lcd(1,1,read_1302(0x83)%10+'0');
write_lcd(1,0,0xc8);break;
case 4: xshi=xshi/16*10+xshi%16;
xshi--;if(xshi==0)xshi=23;
xshi=xshi/10*16+xshi%10;
write_1302(0x84,xshi);
write_lcd(1,0,0xc4);
write_lcd(1,1,read_1302(0x85)/10+'0');
write_lcd(1,1,read_1302(0x85)%10+'0');
write_lcd(1,0,0xc5); break;
case 5: ri=ri/16*10+ri%16;
ri--;if(ri==0)ri=31;
ri=ri/10*16+ri%10;
write_1302(0x86,ri);
write_lcd(1,0,0x88);
write_lcd(1,1,read_1302(0x87)/10+'0');
write_lcd(1,1,read_1302(0x87)%10+'0');
write_lcd(1,0,0x89); break;
case 6: yue=yue/16*10+yue%16;
yue--;if(yue==0)yue=12;
yue=yue/10*16+yue%10;
write_1302(0x88,yue);
write_lcd(1,0,0x85);
write_lcd(1,1,read_1302(0x89)/10+'0');
write_lcd(1,1,read_1302(0x89)%10+'0');
write_lcd(1,0,0x86); break;
case 7:nian=nian/16*10+nian%16;
nian--;if(nian==-1)nian=99;
nian=nian/10*16+nian%10;
write_1302(0x8c,nian);
write_lcd(1,0,0x82);
write_lcd(1,1,read_1302(0x8d)/10+'0');
write_lcd(1,1,read_1302(0x8d)%10+'0');
write_lcd(1,0,0x83); break;
}
write_1302(0x8e,0x80);

}
}
} //

void xianshi_lcd()
{
unsigned int T=0;
unsigned char zheng,xiao;
T=read_temp();
zheng=T>>4;
xiao=T&0x000f;
write_lcd(1,0,0x80); //第一行显示

write_lcd(1,1,'2');
write_lcd(1,1,'0');
write_lcd(1,1,read_1302(0x8d)/10+'0');
write_lcd(1,1,read_1302(0x8d)%10+'0');
write_lcd(1,1,'-');
write_lcd(1,1,read_1302(0x89)/10+'0');
write_lcd(1,1,read_1302(0x89)%10+'0');
write_lcd(1,1,'-');
write_lcd(1,1,read_1302(0x87)/10+'0');
write_lcd(1,1,read_1302(0x87)%10+'0');
write_lcd(1,1,' ');

write_lcd(1,1,zheng/10+'0');
write_lcd(1,1,zheng%10+'0');
write_lcd(1,1,'.');
write_lcd(1,1,xiao*10/16+'0');

write_lcd(1,0,0xc4); //第二行显示

write_lcd(1,1,read_1302(0x85)/10+'0');
write_lcd(1,1,read_1302(0x85)%10+'0');
write_lcd(1,1,':');
write_lcd(1,1,read_1302(0x83)/10+'0');
write_lcd(1,1,read_1302(0x83)%10+'0');
write_lcd(1,1,':');
write_lcd(1,1,read_1302(0x81)/10+'0');
write_lcd(1,1,read_1302(0x81)%10+'0');
write_lcd(1,1,' ');
write_lcd(1,1,read_1302(0x8b)+'0');
}
void main()
{
init_1302();
init_lcd();
init2();
while(1)
{gnmod();


} }

void time0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
xianshi_lcd();
}










northcan 2011-08-15
  • 打赏
  • 举报
回复
要锲而不舍,不怕失败。
lbing7 2011-08-15
  • 打赏
  • 举报
回复
慢慢来,都会有个过程的。。

复杂的表达式,自己要慢慢学会分解成简单的,最后理解之

yy304964313 2011-08-15
  • 打赏
  • 举报
回复
不用灰心,搞多了就懂了
schlafenhamster 2011-08-14
  • 打赏
  • 举报
回复
i=i&(~((0X01)<<(num))); //VB 的残留
i &= ~(0X01<<num); // C想法
jj89816657 2011-08-14
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 able200330 的回复:]
楼主不要紧,C语言的运算符,&与 是 1 1 ->1
1 0 ->0
0 1 ->0
0 0 ->0 这些看下书就知道了,
学单片机与C可以共同进步。
[/Quote]
你也是新人吗?妹子~~
able200330 2011-08-14
  • 打赏
  • 举报
回复
楼主不要紧,C语言的运算符,&与 是 1 1 ->1
1 0 ->0
0 1 ->0
0 0 ->0 这些看下书就知道了,
学单片机与C可以共同进步。
dceacho 2011-08-14
  • 打赏
  • 举报
回复
真不明白为什么这样写,虽然短,但看起来费劲,还不如直接写个函数

uchar clrbit(uchar dat,uchar bit)
{
switch(bit)
{
case 0:return(dat&0xfe);
case 1:......
.......
}
}
dfwxj 2011-08-13
  • 打赏
  • 举报
回复
楼主是要多充电,我没学过的人都看懂了。只将指定的那一位清零,其他位不变。如果不先取反,则是将除指定位外的其他位清零。
无心 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jj89816657 的回复:]

引用 3 楼 ksvhxd 的回复:
i=i&amp;(~((0X01)<<(num)));
这条语句的直译就是将变量i的num位清零。

解释如下:将0x01左移num位,再按位求反后和变量i进行按位“与”运算后再存入变量i中。

如:num = 3;
0x01<<num 就是二进制数00000001左移3位 结果是00001000 求反 为11110111再和i与 就把……
[/Quote]

在C语言中,与"&" 或"|" 是C51位运算的两个常用运算符,主要作用是就是 位清零和置位
如 i=i&0xf0; 就是将i的低4位清零,而高4位不受影响。
i=i|ox80; 就是将i的第7位置1,而其它的位不受影响。
七色鸟 2011-08-13
  • 打赏
  • 举报
回复
不懂,顶了!
Jackindata 2011-08-13
  • 打赏
  • 举报
回复
我没有学51,在学TI的msp430 。学了大半年,快要结束了,晚些时候转而学习ARM。
AnYidan 2011-08-13
  • 打赏
  • 举报
回复
i=~((0x01)<<(num)),

影响别的位了
AnYidan 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ksvhxd 的回复:]
i=i&(~((0X01)<<(num)));
这条语句的直译就是将变量i的num位清零。

解释如下:将0x01左移num位,再按位求反后和变量i进行按位“与”运算后再存入变量i中。

如:num = 3;
0x01<<num 就是二进制数00000001左移3位 结果是00001000 求反 为11110111再和i与 就把i的3位清零了。
[/Quote]

lz 的 c 不扎实
jj89816657 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ksvhxd 的回复:]
i=i&(~((0X01)<<(num)));
这条语句的直译就是将变量i的num位清零。

解释如下:将0x01左移num位,再按位求反后和变量i进行按位“与”运算后再存入变量i中。

如:num = 3;
0x01<<num 就是二进制数00000001左移3位 结果是00001000 求反 为11110111再和i与 就把i的3位清零了。
[/Quote]
为什么要&呢,直接i=~((0x01)<<(num)),不是一样吗,我看到很多程序都要&那么一下~其实我这样也对吧
jj89816657 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 duojinian 的回复:]
不建议用C语言直接“翻译”标准时序图,因为C编译后,的时序基本和时序图偏差较大。无法正确运行。
建议用汇编翻译时序图。
例如上面那句话,你可以看看反汇编代码,根据系统晶体频率计算一下实际运行时间是多少。肯定和标准时序图有较大偏差。
假设num = 1,
0x01 << 1; 就是左移1位, 0x02;
~(0x02) = 0FD; = 1111,1101(二进制)
i = i &……
[/Quote]
为什么要&呢,直接i=~((0x01)<<(num)),不是一样吗,我看到很多程序都要&那么一下~其实我这样也对吧
haoziccy 2011-08-13
  • 打赏
  • 举报
回复
我也是新人,受教受教。
楼主别灰心,我都断断续续的学了1年了,学了半年的汇编,然后开始学C,至今还不能驾驭51。所以楼主不要灰心,慢慢来嘛。
无心 2011-08-13
  • 打赏
  • 举报
回复
i=i&(~((0X01)<<(num)));
这条语句的直译就是将变量i的num位清零。

解释如下:将0x01左移num位,再按位求反后和变量i进行按位“与”运算后再存入变量i中。

如:num = 3;
0x01<<num 就是二进制数00000001左移3位 结果是00001000 求反 为11110111再和i与 就把i的3位清零了。
DISINHUI 2011-08-13
  • 打赏
  • 举报
回复
标准汇编如下:
mov A,01H
mov R3,A
。。。
loop_1:
ll R3
sdz num
jmp loop_1

mov a,R3
andm A,i
DISINHUI 2011-08-13
  • 打赏
  • 举报
回复
不建议用C语言直接“翻译”标准时序图,因为C编译后,的时序基本和时序图偏差较大。无法正确运行。
建议用汇编翻译时序图。
例如上面那句话,你可以看看反汇编代码,根据系统晶体频率计算一下实际运行时间是多少。肯定和标准时序图有较大偏差。
假设num = 1,
0x01 << 1; 就是左移1位, 0x02;
~(0x02) = 0FD; = 1111,1101(二进制)
i = i & 0xFD(二进制1111101);就是将i(二进制)的第二位清零,其余位不变。

一般用来做跑马灯之类的用途。低电平亮灯。

27,382

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧