Arduino продолжает зацикливаться

Я написал программу, в которой я ввожу число (4 бита), и четыре светодиода на макете загораются в соответствии с его двоичным кодом. Проблема в том, что программа работает хорошо только для (2-15), но если я ввожу 0 или 1, она продолжает зацикливаться, и последовательный монитор продолжает печатать это число. Если я удалю «prbline» из кода, программа будет работать, но последовательный монитор печатает входной номер только в том случае, если он равен 0 или 1. Почему это так?

#include<stdlib.h>
#include<string.h>
int red1=2;
int red2=3;
int red3=4;
int red4=5;
int num=1; // это входной номер
char number[4];
int len;
char str3[]="000",str2[]="00",str1[]="0",str[]="0000";

void setup() {
  // поместите сюда свой код установки для однократного запуска:
  pinMode(red1,OUTPUT);
  pinMode(red2,OUTPUT);
  pinMode(red3,OUTPUT);
  pinMode(red4,OUTPUT);
  itoa (num,number,2);
  len=strlen(number);
  Serial.begin(9600);
  Serial.println(num);
  Serial.println(number);
  Serial.println(len);
  Serial.println(str);


  if(len==1){
    strcat(str3,number);
    strcpy(str,str3);
    }
  else if(len==2){
    strcat(str2,number);
    strcpy(str,str2);
    }
  else if(len==3){
    strcat(str1,number);
    strcpy(str,str1);
    }
  else {
    strcpy(str,number);
    }
  Serial.println(str); //prbline

}

void loop() {
  // поместите сюда свой основной код для многократного запуска:
  if(str[0]=='1'){
    digitalWrite(red1,HIGH);
    }
  if(str[1]=='1'){
    digitalWrite(red2,HIGH);
    }
  if(str[2]=='1'){
    digitalWrite(red3,HIGH);
    }
  if(str[3]=='1'){
    digitalWrite(red4,HIGH);
    }

}

, 👍0

Обсуждение

Как вы предоставляете входные данные?, @Vaibhav

Я меняю значение переменной 'num' из IDE и загружаю, @Maksud Chowdhury


3 ответа


0

Вы перезаписываете память.

 if(len==1){
    strcat(str3,number);
    strcpy(str,str3);
    }

В строке str3 есть место для трех символов, однако вы можете использовать strcat для добавления дополнительных символов.

Я не понимаю вашу технику, однако это может помочь заставить ее работать:

char str3[6]="000",str2[6]="00",str1[6]="0",str[6]="0000";
,

Большое спасибо за ответ, он мне очень помог., @Maksud Chowdhury


1

Столько ошибок в таком коротком коде:

  • число слишком короткое для более чем 3-битных чисел (8 и выше)
  • strcat изменяет первую строку, поэтому все строки str1, str2, str3 слишком короткие
  • если вы захотите использовать их более одного раза, к ним придется добавлять строку снова и снова.....

По сути, если вы снова и снова видите выходные данные установки, это означает сбой и запуск с вектора сброса.

Но главный вопрос заключается в том, почему бы вам не использовать битовые манипуляции с числом напрямую:

  digitalWrite(red1, (num & 0b1000) != 0 ); 
  digitalWrite(red2, (num & 0b0100) != 0 );
  digitalWrite(red3, (num & 0b0010) != 0 );
  digitalWrite(red4, (num & 0b0001) != 0 );

Или с использованием битовых позиций:

  digitalWrite(red1, (num & (1 << 3)) != 0 ); 
  digitalWrite(red2, (num & (1 << 2)) != 0 );
  digitalWrite(red3, (num & (1 << 1)) != 0 );
  digitalWrite(red4, (num & (1 << 0)) != 0 );

Позиции битов становятся немного более читабельными при использовании макроса _BV (который преобразуется в 1 << ..)

  digitalWrite(red1, (num & _BV(3)) != 0 ); 
  digitalWrite(red2, (num & _BV(2)) != 0 );
  digitalWrite(red3, (num & _BV(1)) != 0 );
  digitalWrite(red4, (num & _BV(0)) != 0 );

или более интересную оболочку макроса bit_is_set, чтобы было удобнее читать:

  digitalWrite(red1, bit_is_set(num,3)); 
  digitalWrite(red2, bit_is_set(num,2));
  digitalWrite(red3, bit_is_set(num,1));
  digitalWrite(red4, bit_is_set(num,0));

И, в качестве бонуса, это можно сделать даже в цикле:

byte reds[] = { 5, 4, 3, 2 }; // чтобы сохранить тот же порядок, что и в вопросе
byte num    = 1;

void loop() {
  byte tmp = num;
  for (byte pin : reds) {
    digitalWrite(pin, tmp & 1);
    tmp >>= 1; // битовый сдвиг на единицу вправо (= деление на 2)
  }
}
,

Большое спасибо за ответ, он мне очень помог., @Maksud Chowdhury


1

Чтобы добавить к краткому ответу KIIV, строку

Serial.println(str); //prbline

проще всего создать без itoa и нулевых вспомогательных строк с помощью

int num = 9; // Тестовый ввод 0 .. 9 (или даже 15 = 0x0F)
void setup() {
 char str[] = "0000";
 byte tmp = num & 0x0F; // ограничение допустимых значений
 for (byte i=3; tmp != 0; i--, tmp >>= 1) 
   if (tmp & 0x01) str[i] = '1';
Serial.begin(9600);
Serial.print(num);
Serial.print(" = ");
Serial.println(str);
}  
,