Проблема с государственным автоматом Arduino с государственным автоматом

#c #arduino

Вопрос:

Поэтому я хотел создать государственную машину, которая получает входную букву от пользователя и выводит код морсекода с помощью светодиода. Я использовал переключатель, но по какой-то причине он не хочет работать. Это работало только для буквы а, когда я добавил еще одну букву, она перестала работать.

Я использовал 3 функции (точка, линия и пауза) и объединил их для мигания светодиода. Нам не разрешается использовать «задержку()» в нашей школе, поэтому я сделал таймер.

 #include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define STATUS_IDLE (0)
#define STATUS_A (1)
#define STATUS_B (2)


// Global Variables
unsigned char status;
unsigned long int t_ref; // Reference time
unsigned char last_PINB;
unsigned char mainStatus;
// define inputs and outputs

#define OUTPUT_H1_LAMPE (PC0)

// whenever a variable is used by both, Interrupt and main programm we
// need to tell the compiler about it ==> volatile
volatile unsigned long int millisekunden; // milli seconds timer
unsigned long int last_msg;               //
char buffer[128];
unsigned int c;
unsigned int counter;

void setup() {
  DDRC |= (1 << OUTPUT_H1_LAMPE);

  // Timer 0 konfigurieren
  TCCR0A = (1 << WGM01);               // CTC Modus
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
  // ((16000000/64)/1000) = 25
  OCR0A = 250;

  // Compare Interrupt erlauben
  TIMSK0 |= (1 << OCIE0A);

  Serial.begin(9600);
}

int last_char = -1;

void dot() {
  while (millisekunden - t_ref <= 300) {
    if (millisekunden - t_ref > 300) {
      t_ref = millisekunden;
      break;
    }
    PORTC |= (1 << OUTPUT_H1_LAMPE);
  }

}

void line() {
  while (millisekunden - t_ref <= 900) {
    if (millisekunden - t_ref > 900) {
      t_ref = millisekunden;
      break;
    }
    PORTC |= (1 << OUTPUT_H1_LAMPE);
  }
}
void pause() {
  while (millisekunden - t_ref <= 300) {
    if (millisekunden - t_ref > 300) {
      t_ref = millisekunden;
      break;
    }
    PORTC amp;= ~(1 << OUTPUT_H1_LAMPE);
  }

}



void loop() {

  if (millisekunden - last_msg >=1000) {
    sprintf(buffer, "t=[%lu] state=[%d] PORTC=[%2.2x] t_ref=[%lu]",
            millisekunden, mainStatus, PORTC, t_ref);
    Serial.println(buffer);
    last_msg = millisekunden;
  }


  // user input => get key ...
  if (Serial.available())
  {
    last_char = Serial.read(); // Read a character
    sprintf(buffer, "you have pressed the [%c]-key", (char)last_char);
    Serial.println(buffer);
  }
  if (tolower(last_char) == 'a') {
    t_ref = millisekunden;
    mainStatus = STATUS_A;
    last_char = -1;
  }

  if (tolower(last_char) == 'b') {
    t_ref = millisekunden;
    mainStatus = STATUS_B;
    last_char = -1;
  }

 
  switch (mainStatus) {

    case STATUS_IDLE:
      PORTC amp;= ~(1 << OUTPUT_H1_LAMPE);
      break;
    case STATUS_A:
      dot();
      pause();
      line();
      mainStatus = STATUS_IDLE;
      break;
    case STATUS_B:
      line();
      pause();
      dot();
      pause();
      dot();
      pause();
      dot();
      mainStatus = STATUS_IDLE;
      break;

  }

}

// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
  millisekunden  ;
}```
 

Ответ №1:

Об этом коде можно было бы многое сказать. Я действительно не понимаю, почему ты делаешь все именно так, как ты есть. Но, если я пойду на малейшее изменение, которое заставит ваш код работать, это будет выглядеть следующим образом.

У вас есть такой шаблон, повторяющийся в вашем dot , line , pause :

 while (millisekunden - t_ref <= 300) {
  if (millisekunden - t_ref > 300) {
    t_ref = millisekunden;
    break;
  }
  PORTC |= (1 << OUTPUT_H1_LAMPE);
}
 

Я принял dot это за вышесказанное. Иногда то, что произойдет millisekunden - t_ref <= 300 , будет ложью, millisekunden - t_ref > 300 никогда не будучи правдой. Опять же, я не понимаю, почему вы делаете это таким образом. Но конечным результатом является то, что иногда ваш цикл завершается после выполнения t_ref = millisekunden , а иногда он завершается без этого.

Если вы измените их на:

 while (millisekunden - t_ref <= 300) {
  PORTC |= (1 << OUTPUT_H1_LAMPE);
}
t_ref = millisekunden;
 

При таком расположении ваше обновление t_ref всегда будет происходить при выходе из цикла, и программа будет вести себя более или менее так, как я ожидал, надеюсь, так, как вы ожидаете.

На самом деле не имеет смысла продолжать устанавливать бит PORTC , но, как я уже сказал, малейшее изменение.

Комментарии:

1. Большое спасибо! Я знаю, что мой код не так хорош, я все еще новичок, но я учусь. Еще раз спасибо , вы решили мою проблему! 🙂