qrswll

    1. 学习了
    2. 顶~求助~
    3. :Cry: 顶起来求助
    4. 还有,就是不论我让P1,P3口输出0还是1,各引脚电平都不变,似乎是89C2051根本没工作。
    5. 今天我也产生了这个疑问,百度一下,找到这个帖子了,哈哈~ 不加while(1);在许多情况下是会重复执行的。我今天的这个程序是鲜活的例证=。=
    6. 内容:基本数码管显示+键盘,四位密码....判断一下数是否相等的问题...黑板上写了用6个按键实现,每按一下数字加1可以,到9归0.好好学吧,虽然这个是很初级的东西,但是第一次弄搞出来还是很有成就感的=。=
    7. 原帖由 deweyled 于 2012-5-23 21:27 发表 我觉得你同学3点都没有说错经过多次布板是可以消掉很多过孔,毕竟过孔会影响信号的传输。整个电源线的布局是需要改善。 FPGA下面的推偶电容最好离管脚进一点。但是不是非要横竖一直排放。 纯属个人意见。:lo ...
      我非常支持前辈的看法。我自己画板深有体会,感觉想省事一点,就全部用两面相互垂直的线,用非常多的过孔,很容易一遍就布通了,但是布线完成之后就发现,板子会空好多,不怎么好。所以觉得画板子真是一门艺术,想寻求高稳定性+尽量少的过孔+尽量小的板子。。。
    8. 原帖由 辛昕 于 2012-4-28 00:39 发表 小哥们,最近一两周忙的飞,上次看到你的问题,好长一段,当时连看都没怎么看,不好意思。慢慢来吧,这个五一看来我能休息几天了~~~
      :) 工作很忙吧~加油工作吧=。=
    9. :) 建议也加些直插的=。=直插的我都焊不漂亮。。。估计是焊得少的原因。。。
    10. 刚才在去吃饭的途中我又想到还有一种方法,不过不是在一个程序里面的。。。就是我可以先写个程序给EEPROM相应的地址写入00,这样我读写该地址就可以了~第一次读的是该地址预存的值00~~
    11. 原帖由 辛昕 于 2012-4-19 02:08 发表 U8 ClearFlag; //我说的那个标志 U8 Counter; //你想要的那个计数器 /* Operation on read out ClearFlag from EEPROM */ if(ClearFlag != 0x55) { Counter = 0; ClearFlag = 0x55; /* Operation on ...
      #include<reg52.h>sbit dula=P2^6; //数码管段选sbit wela=P2^7; //数码位选选sbit SDA=P2^0; //IIC数据线sbit SCL=P2^1; //IIC时钟线unsigned char aa,bb,shi,ge,flag,num1;//-------数码管数字显示表----//unsigned char code table[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//------uS级延时函数----//void delay(){;;}//-----mS级延时函数----//void delay1(unsigned char x){unsigned char a,b;for(a=x;a>0;a--)for(b=100;b>0;b--);} //--------IIC总线函数----//void start() //IIC总线起始{SDA=1;delay();SCL=1;delay();SDA=0;delay();}void writebyte(unsigned char writedata) //IIC写字节{unsigned char temp,i;temp=writedata;for(i=0;i<8;i++){ SCL=0; delay();temp=temp<<1;SDA=CY;delay();SCL=1;delay(); } SCL=0; delay();SDA=1; delay(); } unsigned char readbyte() //IIC读字节{unsigned char i,j;for(i=0;i<8;i++){SCL=0;delay();j=(j<<1)|SDA;delay();SCL=1;delay(); }return j;}void ACK() //IIC应答{unsigned char i;SCL=0;delay();if(SDA==1&&i<250){i++;}SCL=1;delay();SCL=0;delay();}void stop() //IIC总线结束{SDA=0;delay();SCL=1;delay();SDA=1;}//-------数码管显示函数--------//void display(unsigned char one,unsigned char two){ if(bb==1){P0=0x00; //消隐dula=1;P0=table[one];dula=0;P0=0xff;wela=1;P0=0xfe;wela=0;}if (bb==2){ dula=1;P0=table[two];dula=0;P=0xff;wela=1;P0=0xfd;wela=0; bb=0;}}//---------初始化函数----------//void init(){ TMOD=0x11; //开定时器0和1TH0=(65536-10000)/256;TL0=(65536-10000)%256;TH1=(65536-1000)/256;TL1=(65536-1000)%256;EA=1;ET0=1;ET1=1;TR0=1;TR1=1;start(); //读EEPROM的0x03地址空间,即标志位的值存放的空间writebyte(0xa0);ACK();writebyte(0x03);ACK();start();writebyte(0xa1);ACK();flag=readbyte();stop();if(flag!=0x99) //标志位flag,判断,如果是第一次上电,给0x08地址初始化值0x00;疑问发源地2。{start(); writebyte(0xa0);ACK();writebyte(0x08);ACK();writebyte(0x00);ACK();stop(); delay1(10);start(); //同时给标志位flag赋值=判断的值,防止下次上电再初始化00.writebyte(0xa0);ACK();writebyte(0x03);ACK();writebyte(0x99); //标志位的判断换成0x96,0x94之类的都会有BUG,重新上电后总是从23开始计数ACK();stop(); } start(); //如果不是第一次上电,则读取0x08里面的值num1(0x08是真正数据存储地址,不是标志位地址)writebyte(0xa0);ACK();writebyte(0x08);ACK();start();writebyte(0xa1);ACK();num1=readbyte();stop();}//-----主函数--------//void main(){init();while(1){ start(); //每执行一次while循环都把计数值num1写入0x08地址中,方便重新上电后读取,继续计数。writebyte(0xa0);ACK();writebyte(0x08);ACK();writebyte(num1);ACK();stop(); shi=num1/10; //两位数码管十位个位值的计算ge=num1%10;display(shi,ge);}}//-----定时器0中断,负责计数值加加以及清零-----//void timer0 () interrupt 1{TH0=(65536-10000)/256;TL0=(65536-10000)%256;aa++;if(aa==100){aa=0;num1++;}if(num1>=100) //疑问发源地1。。。{num1=0;}}//-----定时器1中断,负责数码管现实中需要的延时,满足视觉暂留------//void timer1 () interrupt 3{TH1=(65536-1000)/256;TL1=(65536-1000)%256;bb++;}复制代码 [ 本帖最后由 qrswll 于 2012-4-20 10:10 编辑 ]
    12. 原帖由 辛昕 于 2012-4-19 02:00 发表 这事我干过类似的。第一次我没办法,但第二次我有办法。 上电之初,不要直接在程序里把该单元清零。 在程序运行时,做一个子函数,当某个按键或者遇到什么条件时,就把该单元清零,从此,它就是零了。这样 ...
      :) 谢谢学长的指点。学长这段话一开始说的项目里的做法我觉得比较符合实际的使用情况,因为这又不是做定时炸弹,非要在第一次上电的时候取初值为0(而且是关电源计时会停止的炸弹,计数还是往上加的...一般都是倒计时=。=) 在实际应用中,可以设一个按键,按下时将计数值清零,是很不错的选择。如果需要在第一次上电就为0,再按一下清零键就好了。 学长后面想到的方法是一种低概率出错的方法,这里是8位存储数据,那么出错的概率就是1/256,在调试程序的时候,我每次都要把判断的标志位的值改一下,因为是存在EEPROM中的,所以上一次写入的值被保存在了同一个存储空间,想在下一次中调试就跳过了00初值的赋值了=。=(实际上觉得换个地址存也可以~)。刚开始的时候遇到好多问题,一开始是IIC总线读和写的时候,总是得不到想要的效果,我估计是程序执行得太快了,造成时序冲突,于是在两次写之间加了一个delay(10),想要的效果出来了,上电第一次会有初值,后面断电后,在原基础累加。 但是还是有些瑕疵,就是第一次上电的时候先是显示一个乱码,然后才跳成00。这我就不太懂了,调试了好多次,误打误撞把这个错误解决了,就是在解决之后我到现在都没明白是为什么。。。我在程序中用定时器中断进行计时,定时器中装入10ms,取变量aa==100的时候,得到1S的定时,完成两位数的数码管时间显示。其中有一句话是 if(num==100){num=0;}我把判断条件变成if(num>=100){num=0;},一开始的乱码就没有了。我估计是一开始还是读了EEPROM存储器里面的值。。。num设定的是unsigned char类型的。num通过num/10和num%10分别得到个位和十位显示的值。这是我的第一个疑问=。= 第二个疑问是这样发现的:在我基本实现了功能要求后,多次尝试修改标志位的值,但是发现了一个BUG.......在我设标志位为0x96和0x94的时候,断电再上电后计数的值并没有按照递增的顺序,而是从23开始往上加,无论当前计数值是多少,断电再上电都是23........不知道是什么原因 求学长指点:) 估计三言两语也说不清=。=代码贴在楼下~ [ 本帖最后由 qrswll 于 2012-4-20 08:33 编辑 ]
    13. 原帖由 辛昕 于 2012-4-17 15:39 发表 郭老师的视频对入门很有帮助,但入门以后还要学习更多更规范,看看其他人不同的思路。
      概述:一个掉电计数数据保存的程序,第一次上电初值为00,(计数值++,加至99归0),以后每次断电再次上电后,能接着断电前的计数值继续计数。   学长,这两天我学习了IIC总线存储器EEPROM的读写方法,视频教程老师说了一道题,要求实现掉电计数保持功能,即用定时器计数,每次数字改变都将变化的数字存入EEPROM,这样即使掉电了,再次上电立即读取EEPROM里面的值,可以在上次计数值的基础上继续往上加。 我编的程序是在主函数里面写了一个利用IIC总线读写EEPROM的程序,这样可以完成掉电保持,但是如果是这样,当我第一次启动程序时(此时从未对EEPROM相应的存储地址里写过值),应该是一个随机值,或者是根据说明书全1或者全0,我想把第一次程序启动时的值固定为00,但是想不出有什么办法。考虑了两种情况: 1.如果在主函数里面初始化令计数初值为0的话,掉电后上电,就不能读出上次的值了,不能完成功能。 2.如果计数初值赋0后,再读EEPROM里存的值,那么赋值的0被覆盖,毫无意义。。。 想了好久现在还没有想出有什么办法可以解决,求学长指点=。= [ 本帖最后由 qrswll 于 2012-4-17 16:06 编辑 ]
    14. 原帖由 辛昕 于 2012-4-17 15:41 发表 不要乱叫前辈,我很年轻。要是找不到媳妇,你给我找啊?:pleased:
      学长=。=
    15. 原帖由 辛昕 于 2012-4-15 01:46 发表 说到了这个delay。建议楼主学习一下其他方式的延时方法,这种纯粹靠循环递减方式的延时方法,只有在这种学习的代码中才能见到,真正实用的程序中这样写,再高的CPU也会让你弄得非常迟钝。
      :carnation: 前辈回答得好耐心=。=不对...以后就叫前辈学长了~~:) 仔细研读了学长的回答,觉得如果偶尔复位出现了1,想下次刚好还在那个位置出现1的话...说不定可以去买彩票了.......我看的是郭天祥的视频,暂时学到的只是delay().......看来在实际应用中,应该少用delay()......其他的延时方法,是指定时器么?还是有一些更好的方法呢?
    16. 原帖由 辛昕 于 2012-4-13 09:26 发表 额,更可能的原因是,根本没到定时器来加1,你复位后到显示这段时间里,根本还没来一次定时器。你的定时器长度是 10000,晶振是多少?定时长度是多久? 从你的主程序来看,比较简单,整个执行过程很可能才上百 ...
      :) 非常感谢前辈的指点。 1.前辈在第一条回复中说的对,我那个aa纯属多余,现在总结起来是自己陷入了思维定势,一般定时时间长的时候总是设一个中间变量,但是这里需要的是1%S,所以就不需要了。同时我这样贴代码确实是有问题的,昨天我也看了一些专业人士写的代码,注释很全,很规整,下次问问题的时候我会把代码写得更加规范。   2.前辈的第二条回复解决了我疑惑中的其中一种情况:按下key1后,再按key3复位。因为之前按下key1,定时器已经被关掉,所以按key3的时候肯定是0,不会往上加。   3.我用的晶振是11.0592MHz,定时器长度是10ms~     我的疑惑中的另一种情况是,没有按下key1,直接按key3的复位。我仔细想了一下这种情况,如果我按住key3不松手(中断结束了我还没松手),那么主程序因为while(1);循环执行,根据程序长度和机器周期,每循环一次的时间是us级的(不包括display),所以即使某一次中断刚好进入了 bai=bb/100; shi=bb%100/10; ge=bb%10;的后面,将bb变成1,可是由于key3键我还没松手,循环一次之后,bb又变成0,0----1-----0,数字变化中间间隔us级是非常短的,人眼察觉不到。 如果刚好发生了非常小概率的事件:   bb=0;  bai=bb/100;  shi=bb%100/10;  ge=bb%10; 这段之后进入中断,无论是在中断结束刚好松手key3,还是中断正在进行时松手key3,中断程序依旧执行至结束,回到主程序后,执行 if(key1==1){TR0=1;},显示1,过10ms显示2,依次递增。这时候好像就不符合要求了(从1开始复位的)。。。不过这个概率好像很小。。。? 以上是我的一些理解,可能逻辑上存在一些错误。。。还请前辈指正。。。 前辈的第三个回复:当定时器长度和这个时间(程序执行时间)相比而言差别比较大时,你的这种考虑就不可能出现。 我有些理解不过来。。。为什么定时器长度和程序执行时间相差较大的时候,我这种情况就不会出现呢?中断不会进入 bai=bb/100; shi=bb%100/10; ge=bb%10;的后面么? :)  [ 本帖最后由 qrswll 于 2012-4-14 09:16 编辑 ]
    17. :Sweat:
    18. :Sweat: 顶起来
    19. 基础的LED灯和数码管同时点亮的问题 7/16512 51单片机 2012-04-10
      非常感谢楼上几位前辈的指点。经过一个上午的努力,我把这个问题和相关的许多问题都解决啦:) 谢谢各位:) 去吃午饭了~
    20. 基础的LED灯和数码管同时点亮的问题 7/16512 51单片机 2012-04-08
      原帖由 jishuaihu 于 2012-4-8 19:41 发表 用delay肯定不合适,因为你把时间都浪费到了delay里面,数码管显示当然就不能稳定了,闪烁和稳定是个矛盾,要CPU同时完成用delay不好吧。当然这样的要求是可以满足的,那就是你一直跑着显示的函数,然后用一个计数标 ...
      :) 斑竹前辈大好人=。=给我提示了一个很好的思路,明天我就去试验一下。 还有,我的一个疑问是,在我的问题中,为什么数码管总有一位是稳定的呢?我理解自己的程序,好像delay(100)干扰到每个数码管的显示了,但是总会有一位显示是稳定的(比如像点亮4个数码管,这样的程序前3个数码管是闪烁的,但是最后一个数码管是稳定显示的)。

最近访客

< 1/1 >

统计信息

已有1103人来访过

  • 芯积分:--
  • 好友:2
  • 主题:14
  • 回复:50

留言

你需要登录后才可以留言 登录 | 注册


辛昕 2012-4-20
qrswll: 来学长的空间踩一脚=。=
嘿嘿,好啊
查看全部