首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >状态机的Arduino状态机问题

状态机的Arduino状态机问题
EN

Stack Overflow用户
提问于 2021-06-13 19:58:29
回答 1查看 46关注 0票数 0

所以我想做一个状态机,它从用户那里获取输入字母,并使用LED输出morsecode。我使用了一个开关,但由于某些原因,它不想工作。它只适用于字母a,当我添加另一个字母时,它就停止工作了。

我使用了3个函数(点、线和暂停),并将它们组合起来用于LED的闪烁。我们学校不允许使用"delay()“,所以我做了一个计时器。

代码语言:javascript
复制
#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 &= ~(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 &= ~(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++;
}```
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-13 22:03:25

关于这段代码,我们可以说很多。我真的不明白你为什么要这样做。但是,如果我只做最小的改动,就可以让你的代码正常工作,如下所示。

您在dotlinepause中重复了这种模式

代码语言:javascript
复制
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之后退出,有时它在没有执行t_ref = millisekunden的情况下退出。

如果将这些更改为:

代码语言:javascript
复制
while (millisekunden - t_ref <= 300) {
  PORTC |= (1 << OUTPUT_H1_LAMPE);
}
t_ref = millisekunden;

有了这种安排,当循环退出时,您的t_ref更新将始终发生,并且程序的行为或多或少会按照我期望的方式运行,希望是您期望的方式。

继续在PORTC中设置位也没有什么意义,但正如我所说的,最小的变化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67957986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档