C51单片机应用与C语言程序设计
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

任务3 计数并控制循环次数

任务2中已经通过对C51编程实现对机器人伺服电机的控制,为了让微控制器不断发出控制指令,你用到了以while(1)开头的死循环(即永不结束的循环)。不过在实际的机器人控制过程中,你会经常要求机器人运动一段给定的距离或者一段固定的时间,这时就需要能控制代码执行的次数。

for语句

最方便的控制一段代码执行次数的方法是利用for循环,语法如下:

for(表达式1;表达式2;表达式3)语句

它的执行过程如下:

(1)求解表达式1。

(2)求解表达式2,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面第(3)步;若其值为假(0),则结束循环,转到第(5)步。

(3)求解表达式3。

(4)转回第(2)步继续执行。

(5)循环结束,执行for语句下面的一个语句。

for语句最简单的应用形式,也就是最易理解的形式如下:

   for(循环变量赋初值;循环条件;循环变量增/减值)语句

例如,下面是一个用整型变量myCounter来计数的for循环程序片段。每执行一次循环,它会显示myCounter的值。

    for(myCounter=1;myCounter<=10;myCounter++)
    {
      printf("%d",myCounter);
      delay_nms(500);
    }

在这里,向你介绍新的算术运算符。

自增和自减

C语言有两个很有用的运算符——自增和自减,即“++”和“--”。

运算符“++”是操作数加1,而“--”是操作数减1。换句话说:“x=x+1”同“x++”;“x=x-1”同“x--”。

myCounter ++的作用就相当于myCounter=myCounter+1,只不过这样用起来更简洁。这也是C语言的特点,灵活简洁。

该你了——不同的初始值和终值及计数步长

你可以修改表达式3来使myCounter以不同步长计数,而不是按9,10,11,…来计,你可以让它每次增加2(9,11,13,…)或增加5(10,15,20,…)或任何你想要的步进,递增或递减都可以。下面的例子是每次减3。

    for(myCounter=21;myCounter>=9;myCounter=myCounter-3)
    {
      printf("%d\n",myCounter);
      delay_nms(500);
    }

for循环控制电机的运行时间

到目前为止,你已经理解了脉冲宽度控制连续旋转电机速度和方向的原理。控制电机速度和方向的方法是非常简单的。控制电机运行的时间也非常简单,那就是用for循环。

下面是for循环的例子,它会使电机运行几秒钟。

    for(Counter=1;Counter<=100;i++)
    {
      P1_1=1;
      delay_nus(1700);
      P1_1=0;
      delay_nms(20);
    }

让我们来计算一下这个代码能使电机转动的确切的时间长度。每通过循环一次,delay_nus(1700)持续1.7 ms,delay_nms(20)持续20ms,其他语句的执行时间很少,可忽略。那么for循环整体执行一次的时间是:1.7 ms+20 ms=21.7ms,本循环执行100次,即就是21.7ms乘以100,时间=21.7ms×100=0.0217s×100=2.17s。

假如要让电机运行4.34s,for循环必须执行上面两倍的时间。

    for(Counter=1;Counter<=200;i++)
    {
      P1_1=1;
      delay_nus(1700);
      P1_1=0;
      delay_nms(20);
    }

例程:ControlServoRunTimes.c

● 输入、保存并运行程序ControlServoRunTimes.c;

● 验证是否与P1_1连接的电机逆时针旋转2.17s,然后与P1_0连接的电机旋转4.34s。

    #include<BoeBot.h>
    #include<uart.h>
    int main(void)
    {
      int Counter;

      uart_Init();
      printf("Program Running!\n");

      for(Counter=1;Counter<=100;Counter++)
      {
        P1_1=1;
        delay_nus(1700);
        P1_1=0;
        delay_nms(20);
      }
      for(Counter=1;Counter<=200;Counter++)
      {
        P1_0=1;
        delay_nus(1700);
        P1_0=0;
        delay_nms(20);
      }
      while(1);
    }

假如想让两个电机同时运行,给与P1_1连接的电机发出1.7ms的脉宽,给与P1_0连接的电机发出1.3ms的脉宽,现在每通过循环一次要用的时间是:

1.7ms——与P1_1连接的电机

1.3ms——与P1_0连接的电机

20 ms——中断持续时间

----------------------------------------

一共是23 ms

如果想使机器人运行一段确定的时间,可以计算如下:

脉冲数量=时间/0.023s=时间/0.023

假如想让电机运行3s,计算如下:

脉冲数量=3/0.023= 130现在,可以将for循环中作如下修改,程序如下:

    for(counter=1;counter<=130;i++)
    {
      P1_1=1;
      delay_nus(1700);
      P1_1=0;
      P1_0=1;
      delay_nus(1300);
      P1_0=0;
      delay_nms(20);
    }

例程:BothServosThreeSeconds.c

下面是一个使电机向一个方向旋转3s,然后反向旋转的例子。

● 输入、保存并运行程序BothServosThreeSeconds.c;

    #include<BoeBot.h>
    #include<uart.h>
    int main(void)
    {
      int counter;
      uart_Init();
      printf("Program Running!\n");

      for(counter=1;counter<=130;counter++)
      {
        P1_1=1;
        delay_nus(1700);
        P1_1=0;
        P1_0=1;
        delay_nus(1300);
        P1_0=0;
        delay_nms(20);
      }
      for(counter=1;counter<=130;counter++)
      {
        P1_1=1;
        delay_nus(1300);
        P1_1=0;

        P1_0=1;
        delay_nus(1700);
        P1_0=0;
        delay_nms(20);
      }
      while(1);
    }

验证每个机器人是否沿一个方向运行3s,然后反方向运行3s。你是否注意到当电机同时反向的时候,它们总是保持同步运行?这将有什么作用呢?