打印

C语言的理解

[复制链接]
3711|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
calm_lrc|  楼主 | 2010-9-10 00:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg51.h>
sbit gate=P2^0;
void main(void)
{
unsigned int i,j;
while(1)
{for(i=1000;i>0;i--)
for(j=1000;j>0;j--)
gate=!gate;
}
}

89C51,此程序是一个延时程序,用以控制P20端口的LED的亮灭,线路原理图就不传了,相信大家都知道这个最小单片机系统。
注:晶振的频率为12MHZ。

问:
1、LED是否延迟1S亮灭。
2、两个for循环加while循环是否就代表执行机器周期1M次后对P20取反操作?如果是,那么请问,这个循环程序怎么就代表了执行机器周期1M次呢?是否i--以及j--代表访问了寄存器呢?如果是,1M次怎么来的?

相关帖子

沙发
calm_lrc|  楼主 | 2010-9-10 00:49 | 只看该作者
单片机初学者,一上来就遇到槛,请匠人大哥有时间帮忙解答下,当然,热心的技术同仁如果不嫌问题幼稚,帮帮忙。
如果我的表达还不是很清楚,请告诉我,谢谢各位了。

使用特权

评论回复
板凳
原野之狼| | 2010-9-10 01:02 | 只看该作者
从汇编里看一下都有哪些指令 然后可以大概计算一下延时
keil仿真的时候也能看见这个飞跃时间的 不该还是建议自己计算一下以加深映像

1、LED是否延迟1S亮灭。
   得实测或者查指令再计算
2、两个for循环加while循环是否就代表执行机器周期1M次后对P20取反操作?如果是,那么请问,这个循环程序怎么就代表了执行机器周期1M次呢?是否i--以及j--代表访问了寄存器呢?如果是,1M次怎么来的?
   是1M次循环 不是1M次机器周期

使用特权

评论回复
地板
zq1987731| | 2010-9-10 01:17 | 只看该作者
while(1)
{
      for(i=1000;i>0;i--)
      {
            for(j=1000;j>0;j--)
            {
                  gate=!gate;
            }
      }
}
帮LZ加了点括号,现在这么个形式,如果说LED“亮灭”,那只能是对超高速摄像机而言,事实上这段程序就是在输出个50%占空比的方波...按LZ的本意应该改成如下形式——
while(1)
{
      for(i=1000;i>0;i--)
            for(j=1000;j>0;j--);
      gate=!gate;
}
这样的话,两个for才能构成一个“死机式延时
实际的机器周期会大大超过1M次,首先i和j都是unsigned int型,那么一次操作必然要更改2个字节,这2个变量在你的main中作为局部变量一般而言会由R7开始,比如i占用R7和R6,j则是R5和R4,i--和j--自然就是针对它们的,这样粗略估计一下按12M晶振,12分频的标准8051算,估计8秒左右LED翻转一下状态

使用特权

评论回复
5
ayb_ice| | 2010-9-10 08:22 | 只看该作者
要看反汇编,计算才能知道到底延时了多少时间

使用特权

评论回复
6
calm_lrc|  楼主 | 2010-9-10 10:33 | 只看该作者
从汇编里看一下都有哪些指令 然后可以大概计算一下延时
keil仿真的时候也能看见这个飞跃时间的 不该还是建议自己计算一下以加深映像

1、LED是否延迟1S亮灭。
   得实测或者查指令再计算
2、两个for循环加while循环 ...
原野之狼 发表于 2010-9-10 01:02

如何在汇编里看?

使用特权

评论回复
7
calm_lrc|  楼主 | 2010-9-10 10:35 | 只看该作者
while(1)
{
      for(i=1000;i>0;i--)
      {
            for(j=1000;j>0;j--)
            {
                  gate=!gate;
            }
      }
}
帮LZ加了点括号,现在这么个形式,如果说LED“亮灭”,那只 ...
zq1987731 发表于 2010-9-10 01:17


被你搞晕了.干嘛把我的程序改过来改过去?

使用特权

评论回复
8
calm_lrc|  楼主 | 2010-9-10 10:55 | 只看该作者
4# zq1987731

对LS热心同仁的理解:
1:你说的8s翻转是指"高电平"或者"低电平"持续的时间吗?因为你说了I/O的状态其实是在发送一个方波.
2.你帮我把程序更改了下,能告诉我为什么先执行j而不是i呢?
3.到底这1M次循环,哪里表现了?

使用特权

评论回复
9
冷漠| | 2010-9-10 11:09 | 只看该作者
本帖最后由 冷漠 于 2010-9-10 11:11 编辑

书上早就精确算过了,好像应该写为:
void  delay_ms( int  m )                 //  延时m 毫秒
{
while(m--)                     
{   for( i=0;i  <125;  i++); }           //  1ms延时时间,也可能是250.
}



LZ的程序反汇编是:
?PR?main?TT2         SEGMENT CODE
?DT?main?TT2         SEGMENT DATA
        EXTRN        CODE (?C_STARTUP)
        PUBLIC        main
        RSEG  ?DT?main?TT2
?main?BYTE:
          i?040:   DS   2
          j?041:   DS   2
; #include<reg51.h>
; sbit gate=P2^0;
; void main(void)

        RSEG  ?PR?main?TT2
main:
                        ; SOURCE LINE # 6
; {
                        ; SOURCE LINE # 7
?C0001:
; unsigned int i,j;
; while(1)
                        ; SOURCE LINE # 9
; {for(i=1000;i>0;i--)
                        ; SOURCE LINE # 10
        MOV          i?040,#03H
        MOV          i?040+01H,#0E8H
?C0003:
        SETB         C
        MOV          A,i?040+01H
        SUBB         A,#00H
        MOV          A,i?040
        SUBB         A,#00H
        JC           ?C0001
; for(j=1000;j>0;j--)
                        ; SOURCE LINE # 11
        MOV          j?041,#03H
        MOV          j?041+01H,#0E8H
?C0006:
        SETB         C
        MOV          A,j?041+01H
        SUBB         A,#00H
        MOV          A,j?041
        SUBB         A,#00H
        JC           ?C0005
; gate=!gate;
                        ; SOURCE LINE # 12
        CPL          gate
?C0008:
        MOV          A,j?041+01H
        DEC          j?041+01H
        JNZ          ?C0010
        DEC          j?041
?C0010:
        SJMP         ?C0006
?C0007:
?C0005:
        MOV          A,i?040+01H
        DEC          i?040+01H
        JNZ          ?C0011
        DEC          i?040
?C0011:
        SJMP         ?C0003
?C0004:
; }
                        ; SOURCE LINE # 13
        SJMP         ?C0001
?C0002:
; }
                        ; SOURCE LINE # 14
?C0009:
        RET         
; END OF main

        END

使用特权

评论回复
10
seabada| | 2010-9-10 13:12 | 只看该作者
12M的晶振  你上面的肯定不是1s   你那个直接长亮   能延时吗?

使用特权

评论回复
11
seabada| | 2010-9-10 13:13 | 只看该作者
你就不能写个延时函数吗

使用特权

评论回复
12
calm_lrc|  楼主 | 2010-9-10 13:36 | 只看该作者
9# 冷漠

谢谢冷漠!但是,还是很晕.

使用特权

评论回复
13
calm_lrc|  楼主 | 2010-9-10 13:37 | 只看该作者

使用特权

评论回复
14
zq1987731| | 2010-9-10 14:17 | 只看该作者
1:你说的8s翻转是指"高电平"或者"低电平"持续的时间吗?因为你说了I/O的状态其实是在发送一个方波.

我所指的,是如下两段语句的差异:
第一段:
for(i=1000;i>0;i--)
for(j=1000;j>0;j--)
gate=!gate;
我之所以加上花括号,只是为了更清楚得划分循环语句对应的循环体,这段是你写在while(1)中的,应该先看这么句语句:
================================================
gate=!gate;        //这句是你在翻转电平状态,没任何问题
================================================
接着
for(j=1000;j>0;j--)
gate=!gate;
这就有问题了,你把翻转电平的动作循环了1000次,这已经与你延迟X秒后翻转电平的原意有了冲突
================================================
for(i=1000;i>0;i--)
for(j=1000;j>0;j--)
gate=!gate;
问题更大了,对上面那个循环了1000次的循环体再通过循环变量i重复了1000次,1000×1000=1M,和你的本意更是相距甚远
================================================
那么单纯从语法角度出发,到不如
while(1)
{
      gate=!gate;
}

我之所以在后面加上那个“”,为的是从你本意的角度出发——
for(i=1000;i>0;i--)
for(j=1000;j>0;j--);
gate=!gate;
其中
for(i=1000;i>0;i--)
for(j=1000;j>0;j--);
就是延时,写得再清楚些就是——
for(i=1000;i>0;i--)
for(j=1000;j>0;j--)_nop_();
这下明白了吧...1000×1000次的NOP带来的才是1M次约8秒的延时(12M晶振12分频51的情况下)
然后延时完毕才是翻转电平——
gate=!gate;
2.你帮我把程序更改了下,能告诉我为什么先执行j而不是i呢?

循环体虽然是由外层逐层进入的,但你可以想象,第一次循环时,i为1000,进入后是不是立刻遭遇了如下语句:
for(j=1000;j>0;j--)
gate=!gate;
以上作为一条语句,自然要执行完毕才能执行i为999的第二次循环了。
3.到底这1M次循环,哪里表现了?

1000×1000..................

使用特权

评论回复
15
YINGZEZIGA| | 2010-9-10 15:51 | 只看该作者
ZQ说的没错,程序少一个符号,差之毫厘谬之千里啊。

使用特权

评论回复
16
李进| | 2010-9-10 16:16 | 只看该作者
兄弟,拿个示波器量一下波形,看一下有多少时间,然后调节程序里的参数,以示波器的波形为准.计算的不好

使用特权

评论回复
17
zhlok520| | 2010-9-10 16:33 | 只看该作者
建议楼主还是把C的书好好看看吧。。。

使用特权

评论回复
18
beiwei23du| | 2010-9-10 17:20 | 只看该作者
按照你的写法LED在你的两个for语句中翻转了1000*1000次,算一下LED多长时间闪一次
如果在第二个for语句后加一个分号,LED就会延时两个for语句的时间。这才是你的本意。

使用特权

评论回复
19
cdy200824| | 2010-9-10 17:26 | 只看该作者
4楼说得对,如果可以进行软仿,将时间调到1s!

使用特权

评论回复
20
xzyandrew| | 2010-9-10 17:52 | 只看该作者
mark

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:你知道吗?电子一块是博大精深啊 E-mail:int-lighting2@unilumin.com TEL:0755-29918999511

45

主题

464

帖子

0

粉丝