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);
}
}
3 ответа
Вы перезаписываете память.
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
Столько ошибок в таком коротком коде:
- число слишком короткое для более чем 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
Чтобы добавить к краткому ответу 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);
}
- Bluetooth-модуль HC-05 не принимает AT-команды
- Хранение данных в SDRAM Arduino Portenta H7
- Зачем нужно использовать delay() после использования Serial.flush() в программе
- Servo_Pointer' was not declared in this scope
- Плохие данные : Последовательная связь Arduino Mega и NodeMCU
- Код CRC8 не работает должным образом
- Операторы If/Else на Arduino не выполняются
- Запуск кода кодировщика одновременно с другим кодом в Arduino
Как вы предоставляете входные данные?, @Vaibhav
Я меняю значение переменной 'num' из IDE и загружаю, @Maksud Chowdhury