C在这行代码上提问.“while(--delay>0);“

jyztefdp  于 2023-03-22  发布在  其他
关注(0)|答案(6)|浏览(129)

我正在使用一个PIC来控制一个使用uln 2003驱动板的28 byj-48步进电机。我发现了一个代码,它工作得很完美,但试图理解一行代码在做什么。
搜索后,我没有遇到这个被提出在过去.我是一个新来的C编程和学习其他人的代码.我遇到了这在一个代码,它的工作原理,因为我会期望它.

if(Wait > 0) /* Wait is set in the void main void which calls this in the function*/
{
    delay = Wait;  /*delay takes the value of wait*/
    do {
       while(INTCONbits.T0IF == 0) {} 
       INTCONbits.T0IF = 0;
    } while (--delay > 0);
}

while (--delay > 0);
让我困惑的是,延迟是从一个已知的值中获取的,并传递到一个函数调用中,那么--与它有什么关系呢?
我知道有些语言在读取变量后会将其递减,但据我所知,该值并没有降低。
任何帮助或指针将不胜感激。
编辑以显示更多代码。

void StepMotor(int16_t Count, uint8_t Wait)
{
    static uint8_t state = 0;
    /*  values for half step             0001, 0011, 0010, 0110, 0100, 1100, 1000, 1001*/
    static const uint8_t HalfSteps[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09};
    uint8_t delay;

    do
    {
        if (Count > 0)
        {
            PORTC = HalfSteps[state];   /* drive stepper to select state */
            state++;                    /* step one state clockwise */
            state &= 0x07;              /* keep state within HalfStep table */
            Count--;                    /* update step count */
        }
        else if (Count < 0)
        {
            PORTC = HalfSteps[state];  /* drive stepper to select state */ 
            state--;                   /* step one state counterclockwise */ 
            state &= 0x07;             /* keep state within HalfStep table */ 
            Count++;                   /* update step count */ 
        }
        /* Wait between steps */
        if(Wait > 0) /* Wait is set in the void main void which calls this in the function*/
        {
            delay = Wait;  /*delay takes the value of wait*/
            do {
               while(INTCONbits.T0IF == 0) {} 
               INTCONbits.T0IF = 0;
            } while (--delay > 0);
        }
    } while (Count != 0);
}

void main(void) 
{
    /*
     * Application initialization
     */
    Init_PIC();
    /*
     * Application process loop
     */
    while(1)
    {
        StepMotor(4076, 4);     /* step about 1/2 a revolution clockwise at 4.096 milliseconds per step (about 8 seconds) */
        __delay_ms(1000);
        StepMotor(-2038, 2);    /* step about 1/2 a revolution counterclockwise at 2.048 milliseconds per step (about 4 seconds) */
        __delay_ms(1000);
        StepMotor(-2038, 2);    /* step about 1/2 a revolution counterclockwise at 2.048 milliseconds per step (about 4 seconds) */
        __delay_ms(1000);
    }
}

也许这更有助于得到我的问题的答案什么是“while(--delay〉0);“
做。

sulc1iza

sulc1iza1#

它递减延迟值,然后检查该值是否仍然大于零。如果是,则循环体再次执行。

5sxhfpxr

5sxhfpxr2#

测试(--delay > 0)首先递减delay,并将结果与0进行比较。如果输入的delay值为> 0,则do/while循环将精确地迭代delay次,因此初始测试为if (Wait > 0) {
这些do/while循环令人困惑且容易出错。
问题中的第一个片段更容易理解为:

for (delay = 0; delay < Wait; delay++) {
        while (INTCONbits.T0IF == 0)
            continue;
        INTCONbits.T0IF = 0;
    }

或者可能:

for (delay = Wait; delay > 0; delay--) {
        while (INTCONbits.T0IF == 0)
            continue;
        INTCONbits.T0IF = 0;
    }

同样,由于do/while循环,在StepMotor中,即使Count的初始值为0,函数也会等待,这似乎是不必要的,因为步进电机根本不移动。
下面是一个替代方案:

void StepMotor(int16_t Count, uint8_t Wait) {
    static uint8_t state = 0;
    /*  values for half step             0001, 0011, 0010, 0110, 0100, 1100, 1000, 1001*/
    static const uint8_t HalfSteps[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09};
    uint8_t delay;

    while (Count != 0) {
        if (Count > 0) {
            Count--;                   /* update step count */
            PORTC = HalfSteps[state];  /* drive stepper to select state */
            state++;                   /* step one state clockwise */
            state &= 0x07;             /* keep state within HalfStep table */
        } else {
            Count++;                   /* update step count */ 
            PORTC = HalfSteps[state];  /* drive stepper to select state */ 
            state--;                   /* step one state counterclockwise */ 
            state &= 0x07;             /* keep state within HalfStep table */ 
        }
        /* Wait between steps */
        for (delay = Wait; delay > 0; delay--) {
            while (INTCONbits.T0IF == 0)
                continue;
            INTCONbits.T0IF = 0;
        }
    }
}
ql3eal8s

ql3eal8s3#

John的问题起源于Microchip论坛上的这个topic
John似乎对C语言的一些基本语法和概念感到困惑,为了帮助John,我创建了一个MPLABX project来演示如何格式化C语言文件并实现一个进程循环来执行所描述的动画序列。
John需要考虑一些概念来完全理解代码和使用特定语法的选择。一般来说,C中有三种循环方式:

  • for(sss;ccc;iii);语句
  • while(ccc){}语句
  • do {} while(ccc);语句

请查阅任何C语言参考,以了解有关这些差异的更多详细信息。
在使用Microchip C编译器很长一段时间后,我发现它们可以生成更好的代码,用于使用do {} while(ccc);语句将无符号值倒计时到零。
} while (--delay > 0);语法不够清晰的原因是XC8 C编译器会生成稍微更有效的机器代码。老实说,我经常写这种循环结构,现在只是一种反射。我为使用语法而道歉,因为它会让你学习曲线上升得太快。
你的问题得到了很好的回答,这真是太好了。有些狭隘的偏执狂对你的问题投了反对票,这似乎是一种耻辱。对我来说,它似乎比这里出现的很多问题写得更好。
为了解决在评论中提出的调试问题。Microchip不再出售PIC16F676的AC162052硬件调试头。没有它,这个目标的在线调试是不可能的。

xtfmy6hx

xtfmy6hx4#

--i接近于i --i = i - 1
虽然,它有差异!例如:(在这种情况下)
while(i-- > 0) something();接近:while(i > 0) { i --; something(); },但是
while(--i > 0) something();接近:i --; while(i > 0) { something(); i --; } .

  • 我敢肯定它们之间还有一些其他奇怪的差异,你可以查找pre-incrementpost-increment,正如Saxbophone已经建议的那样。

while(--i > 0);简单地递减i的值,直到它达到0
do; while(--i > 0);执行所有操作,然后递减i,因此它循环直到i达到0,然而i在循环之后仅为0,循环内部的最小i1

int i = 4; // uint8_t and int are SIMILAR
do {
  printf("%d, ", i);
} while(--i > 0);
printf("after: %d", i);

输出:4, 3, 2, 1, after: 0
uint8_t是无符号8位整数。在这种情况下,无符号意味着数字始终为正,它没有负号。

ia2d9nvy

ia2d9nvy5#

让我们换一种方式做吧,我希望这会有帮助。

if(Wait > 0) /* Wait is set in the void main void which calls this in the function */
{
    delay = Wait;  /* delay takes the value of wait */
    do {
        while(INTCONbits.T0IF == 0) {} 
        INTCONbits.T0IF = 0;
        delay = delay - 1;
    } while (delay > 0);
}
snvhrwxg

snvhrwxg6#

我之所以把我的答案添加到这个帖子是因为Microchip网站上的第一个问题,这是一个for循环问题,很快就得到了回答。我展示了我第一次尝试控制步进电机。然而,这是在一个方向启动步进电机,当我按下一个按钮时,电机改变了方向,释放按钮时,电机返回到原来的旋转。
然后我提到,我希望能够设置步骤和步进电机的速度,而不使用按钮。我是在类似于Arduino stepper. h库的东西。
Dan创建了他的代码的第一个版本,用步进电机做了许多动作。这个解决方案非常出色,让我可以用PIC 16 F676芯片对步进电机进行方向、步骤和速度控制。
然后我提到了使用一个简单的归航功能,这样电机就会先归航,然后按照我可以在代码中设置的方向和速度移动。
Dan很快就想出了这个解决方案,现在这给了我stepper.h库可以做的所有事情。他的github上的代码将帮助其他人尝试使用ULN 2003驱动模块使用28 BYJ-48双极步进电机。这使得它非常适合模型动画。
它目前正在制作一个面包板,但一旦我为它创建了立体模型,下周就会展示。
毫无疑问,其他功能可以在未来添加,因为到目前为止,它只使用了PIC的38%的程序字和22%的数据存储器。
Dan的github页面是https://github.com/dsoze1138/16F676_Frameworks

相关问题