找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1513|回复: 17
收起左侧

一个关于C语言for循环做的延时问题

  [复制链接]
ID:284226 发表于 2022-10-1 11:47 | 显示全部楼层 |阅读模式
void delay_ms() //12M晶振,12T为1us
{
unsigned int  i;
    for(i=0; i<32767; i++);
}
上面用的芯片是89C52,仿真用keil51,发现i<32767软件仿真时查看软件正常的延时161ms,但是一旦设为i<32768,一下子就变成1.2s的延时了,烧录代码到芯片,查看LED也是变成1.2s延时。想请教各位大佬为什么会出现这个问题。
回复

使用道具 举报

ID:1034262 发表于 2022-10-1 13:37 | 显示全部楼层
unsigned int  i,i的最大值就是32767,你整个32768,就乱了。
回复

使用道具 举报

ID:332444 发表于 2022-10-1 17:16 | 显示全部楼层
不要希望这种延时能一直准确无异于异想天开受程序其它影响甚大否则的话就不需要中断了
回复

使用道具 举报

ID:41656 发表于 2022-10-1 17:42 | 显示全部楼层
keil仿真要设置正确的时钟
回复

使用道具 举报

ID:161164 发表于 2022-10-1 18:42 | 显示全部楼层
进调试模式看看运行一次走多少步
回复

使用道具 举报

ID:91150 发表于 2022-10-1 21:15 | 显示全部楼层
coody_sz 发表于 2022-10-1 13:37
unsigned int  i,i的最大值就是32767,你整个32768,就乱了。

    ?
回复

使用道具 举报

ID:624769 发表于 2022-10-2 00:41 | 显示全部楼层
这一类的问题,论坛里  问得很多,我也答过很多,你要有心 搜索一下 都能搜到。
delay 函数本来 就不准, 你用 int / unsigned int   就更不靠谱,
你想要 靠谱 一点的话,必须用 unsigned char
void delay()
{
unsigned char  i,j;
        for(i=0;i<200;i++)          //双循环粗调整
        {
         for(j=0;j<150;j++);
         }
        for(i=0;i<50;i++);       //单循环微调整
}
回复

使用道具 举报

ID:824490 发表于 2022-10-2 03:52 | 显示全部楼层

沙发说的没错,uint 的取值范围是0到32767,你要设32768时,变量值溢出了。因为永远到不了32768,所以你这个延时就乱了。你把变量类型改为u32 就可以了
回复

使用道具 举报

ID:332444 发表于 2022-10-2 06:58 | 显示全部楼层
无论是否写错希望这种延时的准确是痴心妄想,否则要时钟芯片何用。
回复

使用道具 举报

ID:284226 发表于 2022-10-2 11:41 | 显示全部楼层
感谢各位大佬指点,但是unsigned int 不是16位的吗?65536?
是的,我发现一旦改成32768,单步调试一看转汇编代码就不对了。比32767时汇编就多少很多步,多用了几个R寄存器。
但是呢,我写成i--居然就正常了。不太理解为什么会这样。感谢大佬提供新的思路。
回复

使用道具 举报

ID:121859 发表于 2022-10-2 13:42 | 显示全部楼层
你看看反汇编代码就知道了,32767时,是按正常汇编语言代码来编制的延时程序,如果是32768则不然,“无符号”在程序代码处理方式上有很大不同的。
当为32767时,代码如下:
C:0x0003    E4       CLR      A
C:0x0004    FF       MOV      R7,A
C:0x0005    FE       MOV      R6,A
C:0x0006    0F       INC      R7
C:0x0007    BF0001   CJNE     R7,#0x00,C:000B
C:0x000A    0E       INC      R6
C:0x000B    BE7FF8   CJNE     R6,#0x7F,C:0006
C:0x000E    BFFFF5   CJNE     R7,#0xFF,C:0006
C:0x0011    22       RET      
当为32768时代码如下:
C:0x0003    900000   MOV      DPTR,#0x0000
C:0x0006    AF82     MOV      R7,DP0L(0x82)
C:0x0008    AE83     MOV      R6,DP0H(0x83)
C:0x000A    E4       CLR      A
C:0x000B    FC       MOV      R4,A
C:0x000C    FD       MOV      R5,A
C:0x000D    FB       MOV      R3,A
C:0x000E    7A80     MOV      R2,#P0(0x80)
C:0x0010    F9       MOV      R1,A
C:0x0011    F8       MOV      R0,A
C:0x0012    D3       SETB     C
C:0x0013    12001C   LCALL    C?SLCMP(C:001C)
C:0x0016    4003     JC       C:001B
C:0x0018    A3       INC      DPTR
C:0x0019    80EB     SJMP     C:0006
C:0x001B    22       RET      
                 C?SLCMP:
C:0x001C    EB       MOV      A,R3
C:0x001D    9F       SUBB     A,R7
C:0x001E    F5F0     MOV      B(0xF0),A
C:0x0020    EA       MOV      A,R2
C:0x0021    9E       SUBB     A,R6
C:0x0022    42F0     ORL      B(0xF0),A
C:0x0024    E9       MOV      A,R1
C:0x0025    9D       SUBB     A,R5
C:0x0026    42F0     ORL      B(0xF0),A
C:0x0028    EC       MOV      A,R4
C:0x0029    6480     XRL      A,#P0(0x80)
C:0x002B    C8       XCH      A,R0
C:0x002C    6480     XRL      A,#P0(0x80)
C:0x002E    98       SUBB     A,R0
C:0x002F    45F0     ORL      A,B(0xF0)
C:0x0031    22       RET      
回复

使用道具 举报

ID:883242 发表于 2022-10-2 17:04 | 显示全部楼层
这是单片机内核指令体系太过于原始的问题,跟c语言有个毛关系???
回复

使用道具 举报

ID:491577 发表于 2022-10-2 20:15 | 显示全部楼层
延时函数不要自己写,STC烧录软件有现成的,直接使用就好。多长时间都可以。比如:
89C52单片机,12M主频
1000ms延时:
void Delay1000ms()                //@12.000MHz
{
        unsigned char i, j, k;

        _nop_();
        i = 8;
        j = 154;
        k = 122;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}
2000ms延时
void Delay2000ms()                //@12.000MHz
{
        unsigned char i, j, k;

        _nop_();
        i = 16;
        j = 51;
        k = 249;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}
回复

使用道具 举报

ID:382454 发表于 2022-10-2 22:08 | 显示全部楼层
延时用官方的程序计算。
回复

使用道具 举报

ID:276663 发表于 2022-10-2 22:45 | 显示全部楼层
编译器对代码的处理方式不同导致的。
回复

使用道具 举报

ID:1046742 发表于 2022-10-5 22:51 | 显示全部楼层
延时用官方的程序计算。
回复

使用道具 举报

ID:284226 发表于 2022-10-6 15:47 | 显示全部楼层
嗯,不管他了。知道有这么个问题就好了,感谢各位大佬指点
回复

使用道具 举报

ID:1047187 发表于 2022-10-10 17:46 | 显示全部楼层
51单片机做不了精准延时,用定时器也只是比for语句好一点
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表