简体   繁体   English

Arduino Uno:当第二次按下时,While 循环无法使用 Button 重置计时器“重新启动”?

[英]Arduino Uno: While-loop fails to "restart" using Button to reset Timer when second-pressing?

What the code does:代码的作用:

  1. The code starts off by showing a short "blinking animation", where segments AF turns on and off one at a time.代码首先显示一个简短的“闪烁动画”,其中片段 AF 一次打开和关闭一个。
  2. The "blinking animation" lasts between 3-10 seconds, upon which a timer starts. “闪烁动画”持续 3-10 秒,然后计时器开始计时。
  3. The timer counts from 0-99 seconds displayed by Digit 1 & 2. While Digit 3 & 4 shows 10th and 100th, respectively, of a second.计时器从数字 1 和 2 显示的 0-99 秒开始计数。而数字 3 和 4 分别显示一秒的第 10 和第 100。
  4. By using the connected button, you can stop the timer by pressing it.通过使用连接的按钮,您可以通过按下它来停止计时器。 Timer stops and shows the time.计时器停止并显示时间。
  5. By pressing down the button a second time it's supposed to restart the timer and send us back to Step 1.通过第二次按下按钮,它应该重新启动计时器并将我们送回第 1 步。

My problem: when I get to STEP 5 in the code, it won't restart.我的问题:当我到达代码中的第 5 步时,它不会重新启动。 The problem is linked to the while-loop in the main function caused by, as far as I can see, the second while-loop in the function "stopTimer".问题与主函数中的 while 循环有关,据我所知,是由函数“stopTimer”中的第二个 while 循环引起的。 Can't make it to exit the loop.无法退出循环。 At least that's what I've understood from all the numerous unsuccessful tries!至少这是我从无数次失败的尝试中了解到的! Tried adding code with if-statements inside the "stopDisplay" function as well, including break;也尝试在“stopDisplay”函数中添加带有 if 语句的代码,包括 break; or return;或返回; etc.等等。

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <avr/io.h>
#include <util/delay.h>

#define BUTTONPRESSED PINC & 1 << PC0

    /*
    - PORT = D
    Segment-A   Pin 1   PD1     0B00000010
    Segment-B   Pin 2   PD2     0B00000100
    Segment-C   Pin 3   PD3     0B00001000
    Segment-D   Pin 4   PD4     0B00010000
    Segment-E   Pin 5   PD5     0B00100000
    Segment-F   Pin 6   PD6     0B01000000
    Segment-G   Pin 7   PD7     0B10000000

    - PORT = B
    Digit 1     Pin 10  PB2     0B00000100
    Digit 2     Pin 11  PB3     0B00001000
    Digit 3     Pin 12  PB4     0B00010000
    Digit 4     Pin 13  PB5     0B00100000

    - PORT = C
    Button      Pin A0  PC0     0B00000001
    */

//Number: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9  in a array.
int segmentNumberArray[10] = {0B01111110, 0B00001100, 0B010110110, 0B10011110, 0B011001100, 0B11011010, 0B11111010, 0B00001110, 0B11111110, 0B11011110};

//Digit: 1, 2, 3, 4   in a array
int digitArrayOff[4] = {0B00000100, 0B00001000, 0B00010000, 0B00100000};
int digitArrayOn[4] = {0B11111011, 0B11110111, 0B11101111, 0B11011111};

//Blinking animation: segment-E, segment-D, segment-C, segment-G, segment-F, segment-A, segment-B, segment-G
int blinkingArray[8] = {0B00100000, 0B00010000, 0B00001000, 0B10000000, 0B01000000, 0B00000010, 0B00000100, 0B10000000};

long number = 0;
int recentTime;
int digit1, digit2, digit3, digit4;
int stopButton;

void startTimer();
void stopTimer();
void choseDigit(int x);
void showNumberOnDisplay(int x);
void blinkingAnimation();

int main()
{

  DDRC = 0;
  DDRD = 255;
  DDRB = 0B00111100; //DDRB = 28;

  srand(time(NULL));

  while (1)
  {
    if (number == 0)
    {
      int randomWaitTime = rand() % 10 + 3; //Calls random number between 3-10
      for (int i = 0; i < randomWaitTime; i++)
      {
        blinkingAnimation();
      }
    }
    startTimer();

    if (BUTTONPRESSED)
    {
      stopButton = 0;
      stopTimer();
    }
    
    if (BUTTONPRESSED)
    {
      break;
    }
  }

  return 0;
}

void startTimer()
{
  PORTD = 0B00000000;                   //Turn ALL segments off
  choseDigit(1);                        //Turn Display 1 on
  showNumberOnDisplay((number / 1000)); //Get value of thousand
  _delay_ms(1);                         //Delay 1 ms

  PORTD = 0B00000000;                         //Turn ALL segments off
  choseDigit(2);                              //Turn Display 2 on
  showNumberOnDisplay((number % 1000) / 100); //Get value of hundred
  _delay_ms(1);                               //Delay 1 ms

  PORTD = 0B00000000;                     //Turn ALL segments off
  choseDigit(3);                          //Turn Display 3 on
  showNumberOnDisplay(number % 100 / 10); //Get value of ten
  _delay_ms(1);                           //Delay 1 ms

  PORTD = 0B00000000;               //Turn ALL segments off
  choseDigit(4);                    //Turn Display 3 on
  showNumberOnDisplay(number % 10); //Get value of single digit
  _delay_ms(1);                     //Delay 1 ms

  number++;
  if (number == 9999) // Reset number count to 1;
  {
    number = 1;
  }
}

void stopTimer()
{
  recentTime = number;
  digit1 = recentTime / 1000;
  digit2 = (recentTime % 1000) / 100;
  digit3 = recentTime % 100 / 10;
  digit4 = recentTime % 10;

  while (stopButton == 0)
  {
    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(1);               //Turn Display 1 on
    showNumberOnDisplay(digit1); //Get value of thousand
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(2);               //Turn Display 2 on
    showNumberOnDisplay(digit2); //Get value of hundred
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(3);               //Turn Display 3 on
    showNumberOnDisplay(digit3); //Get value of ten
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(4);               //Turn Display 3 on
    showNumberOnDisplay(digit4); //Get value of single digit
    _delay_ms(1);                //Delay 1 ms
  }
}

void choseDigit(int x)
{
  PORTB = 0B11111111;
  switch (x)
  {
  case 1:
    PORTB = digitArrayOn[0]; //Display 1 on
    break;

  case 2:
    PORTB = digitArrayOn[1]; //Display 2 on
    break;

  case 3:
    PORTB = digitArrayOn[2]; //Display 3 on
    break;

  case 4:
    PORTB = digitArrayOn[3]; //Display 4 on
    break;
  }
}

void showNumberOnDisplay(int x)
{
  switch (x)
  {
  case 1:
    PORTD = segmentNumberArray[1];
    break;

  case 2:
    PORTD = segmentNumberArray[2];
    break;

  case 3:
    PORTD = segmentNumberArray[3];
    break;

  case 4:
    PORTD = segmentNumberArray[4];
    break;

  case 5:
    PORTD = segmentNumberArray[5];
    break;

  case 6:
    PORTD = segmentNumberArray[6];
    break;

  case 7:
    PORTD = segmentNumberArray[7];
    break;

  case 8:
    PORTD = segmentNumberArray[8];
    break;

  case 9:
    PORTD = segmentNumberArray[9];
    break;

  default:
    PORTD = segmentNumberArray[0];
    break;
  }
}

void blinkingAnimation()
{
  for (int i = 0; i < 8; i++)
  {
    PORTD = blinkingArray[i];
    _delay_ms(125);
  }
}

the value of variable stopButton still 0, resulting stopButton == 0 return true.变量stopButton的值仍然为 0,导致 stopButton == 0 返回 true。 But i think it better to use variable to represent the state.但我认为最好使用变量来表示状态。

#define STATE_COUNT 1
#define STATE_STOP 2
int currentState = 1;
while(1){
  if(currentState == STATE_COUNT && BUTTONPRESSED){
     //do something

     currentState = STATE_STOP;
  }
  if(currentState == STATE_STOP && BUTTONPRESSED){
     //do something

     currentState = STATE_COUNT;
  }
}

edited已编辑

so, my idea is to use STATE to define what code to run.所以,我的想法是使用 STATE 来定义要运行的代码。 so you can eliminate second while loop.所以你可以消除第二个while循环。

while (1) {
  if(currentState == STATE_BLINK){
    blink(); //run code 1 time and change state
    currentState = STATE_COUNT;
  }
  if(currentState == STATE_COUNT){
    startTimer(); 
  }
  if(currentState == STATE_STOP){
    stopTimer(); // while loop inside is removed
  }


  if (BUTTONPRESSED) {
    //change state here
  }
}

void stopTimer() {
  recentTime = number;
  digit1 = recentTime / 1000;
  digit2 = (recentTime % 1000) / 100;
  digit3 = recentTime % 100 / 10;
  digit4 = recentTime % 10;

  PORTD = 0B00000000;          //Turn ALL segments off
  choseDigit(1);               //Turn Display 1 on
  showNumberOnDisplay(digit1); //Get value of thousand
  _delay_ms(1);                //Delay 1 ms

  PORTD = 0B00000000;          //Turn ALL segments off
  choseDigit(2);               //Turn Display 2 on
  showNumberOnDisplay(digit2); //Get value of hundred
  _delay_ms(1);                //Delay 1 ms

  PORTD = 0B00000000;          //Turn ALL segments off
  choseDigit(3);               //Turn Display 3 on
  showNumberOnDisplay(digit3); //Get value of ten
  _delay_ms(1);                //Delay 1 ms

  PORTD = 0B00000000;          //Turn ALL segments off
  choseDigit(4);               //Turn Display 3 on
  showNumberOnDisplay(digit4); //Get value of single digit
  _delay_ms(1);                //Delay 1 ms 
}

void blink(){
 if (number == 0) {
  int randomWaitTime = rand() % 10 + 3; //Calls random number between 3-10
  for (int i = 0; i < randomWaitTime; i++) {
    blinkingAnimation();
  }
 }
}

Here is finally a solution to my problem above.这是我上面问题的最终解决方案。 Thought I post it in case anyone else runs into a similar problem:我想我发布它以防其他人遇到类似的问题:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <avr/io.h>
#include <util/delay.h>

#define BUTTONPRESSED PINC &(1 << PC0)

/*
    - PORT = D
    Segment-A   Pin 1   PD1     0B00000010
    Segment-B   Pin 2   PD2     0B00000100
    Segment-C   Pin 3   PD3     0B00001000
    Segment-D   Pin 4   PD4     0B00010000
    Segment-E   Pin 5   PD5     0B00100000
    Segment-F   Pin 6   PD6     0B01000000
    Segment-G   Pin 7   PD7     0B10000000

    - PORT = B
    Digit 1     Pin 10  PB2     0B00000100
    Digit 2     Pin 11  PB3     0B00001000
    Digit 3     Pin 12  PB4     0B00010000
    Digit 4     Pin 13  PB5     0B00100000

    - PORT = C
    Button      Pin A0  PC0     0B00000001
    */

//Number: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9  in a array
int segmentNumberArray[10] = {0B01111110, 0B00001100, 0B010110110, 0B10011110, 0B011001100, 0B11011010, 0B11111010, 0B00001110, 0B11111110, 0B11011110};

//Digit: 1, 2, 3, 4   in a array
int digitArrayOff[4] = {0B00000100, 0B00001000, 0B00010000, 0B00100000};
int digitArrayOn[4] = {0B11111011, 0B11110111, 0B11101111, 0B11011111};

//Blinking animation: segment-E, segment-D, segment-C, segment-G, segment-F, segment-A, segment-B, segment-G
int blinkingArray[8] = {0B00100000, 0B00010000, 0B00001000, 0B10000000, 0B01000000, 0B00000010, 0B00000100, 0B10000000};

long number = 0;
int recentTime;
int digit1, digit2, digit3, digit4;
int isCounting = 0;
int isButtonDown = 0;

void startTimer();
void stopTimer();
void choseDigit(int x);
void showNumberOnDisplay(int x);
void blinkingAnimation();

int main()
{

  DDRC = 0; // För knappen -->> alt. DDRC&= ~(1 << PC0);
  DDRD = 255;
  DDRB = 0B00111100; //DDRB = 28; -->> detta är för Displayerna

  srand(time(NULL));
  blinkingAnimation();

  while (1)
  {
    if (isCounting == 1)
    {
      startTimer();
    }

    if (BUTTONPRESSED)
    {
      if (isButtonDown == 0)  //Button has not been pressed before
      {
        isButtonDown = 1;
        if (isCounting == 0)
        {
          
          blinkingAnimation();
        }
        else
        {
        isCounting = 0;
        }
      }
    }
    else
    {
      isButtonDown = 0;  //Button has been released
    }

    stopTimer();
  }

  return 0;
}

void startTimer()
{
  PORTD = 0B00000000;                   //Turn ALL segments off
  choseDigit(1);                        //Turn Display 1 on
  showNumberOnDisplay((number / 1000)); //Get value of thousand
  _delay_ms(2.3);                       //Delay 1 ms

  PORTD = 0B00000000;                         //Turn ALL segments off
  choseDigit(2);                              //Turn Display 2 on
  showNumberOnDisplay((number % 1000) / 100); //Get value of hundred
  _delay_ms(2.3);                             //Delay 1 ms

  PORTD = 0B00000000;                     //Turn ALL segments off
  choseDigit(3);                          //Turn Display 3 on
  showNumberOnDisplay(number % 100 / 10); //Get value of ten
  _delay_ms(2.3);                         //Delay 1 ms

  PORTD = 0B00000000;               //Turn ALL segments off
  choseDigit(4);                    //Turn Display 4 on
  showNumberOnDisplay(number % 10); //Get value of single digit
  _delay_ms(2.3);                   //Delay 1 ms

  number++;
  if (number > 5999) // Reset number count to 1;
  {
    number = 1;
  }
}

void stopTimer()
{
  recentTime = number;
  digit1 = recentTime / 1000;
  digit2 = (recentTime % 1000) / 100;
  digit3 = recentTime % 100 / 10;
  digit4 = recentTime % 10;

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(1);               //Turn Display 1 on
    showNumberOnDisplay(digit1); //Get value of thousand
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(2);               //Turn Display 2 on
    showNumberOnDisplay(digit2); //Get value of hundred
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(3);               //Turn Display 3 on
    showNumberOnDisplay(digit3); //Get value of ten
    _delay_ms(1);                //Delay 1 ms

    PORTD = 0B00000000;          //Turn ALL segments off
    choseDigit(4);               //Turn Display 3 on
    showNumberOnDisplay(digit4); //Get value of single digit
    _delay_ms(1);                //Delay 1 ms
}

void choseDigit(int x)
{
  PORTB = 0B11111111;
  switch (x)
  {
  case 1:
    PORTB = digitArrayOn[0]; //Display 1 on
    break;

  case 2:
    PORTB = digitArrayOn[1]; //Display 2 on
    break;

  case 3:
    PORTB = digitArrayOn[2]; //Display 3 on
    break;

  case 4:
    PORTB = digitArrayOn[3]; //Display 4 on
    break;
  }
}

void showNumberOnDisplay(int x)
{
  switch (x)
  {
  case 1:
    PORTD = segmentNumberArray[1];
    break;

  case 2:
    PORTD = segmentNumberArray[2];
    break;

  case 3:
    PORTD = segmentNumberArray[3];
    break;

  case 4:
    PORTD = segmentNumberArray[4];
    break;

  case 5:
    PORTD = segmentNumberArray[5];
    break;

  case 6:
    PORTD = segmentNumberArray[6];
    break;

  case 7:
    PORTD = segmentNumberArray[7];
    break;

  case 8:
    PORTD = segmentNumberArray[8];
    break;

  case 9:
    PORTD = segmentNumberArray[9];
    break;

  default:
    PORTD = segmentNumberArray[0];
    break;
  }
}

void blinkingAnimation()
{
  PORTB = digitArrayOn[4];
  //Random wait time:
  int randomWaitTime = rand() % 10 + 3; //Calls random number between 3-10 seconds

  for (int i = 0; i < randomWaitTime; i++)
  {
    //Blink animation:
    for (int i = 0; i < 8; i++)
    {
      PORTD = blinkingArray[i];
      _delay_ms(125);
    }
  }
  number = 0;
  isCounting = 1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM