AttachInterrupt() повреждает последовательный буфер, требуя перезапуска последовательного порта

Я работаю над экспериментальным АЦП, который позволит «взорвать» то, что находится внутри чипа АЦП, в учебных целях.

В настоящее время у меня есть скетч, в котором кнопка используется в качестве тактового импульса, который подсчитывает (1, 2, 3, 4, ...) для каждого положительного фронта с помощью функции AttachInterrupt().< /п>

Скетч отлично подходит для просмотра данных на последовательном мониторе.

Я соединяю Arduino (Teensy 3.2) с Raspberry Pi, настроенным на считывание данных с последовательной линии в текстовое поле.

После тщательного устранения неполадок выяснилось, что функция attachInterrupt() повреждает последовательный буфер мусором для каждого прерывания. Например, если я использую

Serial1.flush();
Serial1.begin(115200);

сразу после прерывания и затем отправка моих данных с помощью Serial.println() я получаю на выходе ожидаемое десятичное значение. Однако без этих строк я просто получаю мусор Юникода на последовательном выходе. Полный «исправленный» код скетча смотрите ниже:

Мой вопрос: почему это происходит? Мне не нужно будет перезапускать Serial на каждой итерации часов.

#define HWSERIAL Serial1

const int numBits = 12;             //Количество бит в АЦП (разрешение)
const int comparatorPin = 14;       //Номер вывода компаратора
const int clockPin = 15;            //Номер контакта внешнего тактового сигнала (прямоугольный сигнал); ожидаю часы с рабочим циклом 50%
volatile int comparatorState = 0;   //Компаратор высокий или низкий?
volatile bool clockState = 0;       // Часы высокие или низкие?
volatile int masterCount = 0;       //Наш главный счетчик
volatile bool isSameVal = false;    //Совпадает ли значение главного счетчика с прошлым циклом?

int outVal = 0;

int masterBinCount[12];     //Массив для хранения двоичного значения главного счетчика
byte outputPins[12];        //Массив для хранения чисел, связанных с номерами выходных контактов
int maxValue = 0;           //Инициализируем максимальное значение счетчика равным нулю

void setup() {
  Serial.begin(115200);       //Начинаем последовательную передачу
  HWSERIAL.begin(115200, SERIAL_8N1);
  HWSERIAL.flush();
  delay(2000);

  defineOutPins(outputPins);  //Назначаем номера выводов для выходных контактов

  pinMode(14, INPUT);   //Вывод компаратора
  pinMode(15, INPUT);   //Часы входа

  maxValue = pow(2, numBits);   //Устанавливаем максимальное значение счетчика на максимальное битовое разрешение. Бывший. для 12 бит --> 4096
}

void loop() {
  attachInterrupt(clockPin, doOnClock, RISING);   //Когда часы находятся на положительном фронте, выполняем функцию doOnClock

  HWSERIAL.flush();
  HWSERIAL.begin(115200);

  if(isSameVal == false) {    //Если счетчик мастеров НЕ такой же, как в последнем цикле
    convertDecToBin();        //Преобразуем основной счетчик (декабрь) в двоичный формат
    binaryToPins();           //Отправляем двоичное значение (через digitalWrite) на выходные контакты
  }
  else {
    //Ничего не делать
  }
  delay(1000);
}

void defineOutPins(byte pinNos[]) {   //Назначаем номера контактов параллельному двоичному выходу: Pin #0 Teensy 3.2 --> #11
  for(byte i = 0; i < numBits; i++) {
    pinNos[i] = {i};      //Назначаем текущему выводу это значение
    pinMode(i, OUTPUT);   //Определяем контакты как выходы
  } 
}

void doOnClock() {
  comparatorState = digitalRead(comparatorPin);   //Проверяем состояние компаратора

  if(comparatorState >= 0.5) {            //Проверяем, положительный ли тактовый импульс
    if(masterCount == (maxValue - 1)) {   //Проверяем, находится ли текущее значение счетчика на «потолке»
      //Ничего не делать
    }
    else {            //Иначе увеличиваем счетчик
      masterCount++;
    }
  }
  else if(comparatorState < 0.5) {    //Проверяем, отрицательный ли тактовый импульс
    if(masterCount == 0) {            //Проверяем, находится ли текущее значение счетчика на «поле»
      //Ничего не делать
    }
    else {
      masterCount--;    //Иначе уменьшаем обратный отсчет
    }
  }

  isSameVal = false;    //Устанавливаем «законченный» отсчет для этого тактового импульса
}

void convertDecToBin() {
  for(int j = 0; j < numBits; j++) {
    int tempCnt = bitRead(masterCount, j);
    masterBinCount[numBits - (j+1)] = tempCnt;    //Заполняем главный массив двоичных значений в «обратном» порядке, начиная с младшего разряда в самом высоком индексе массива
  }
}

void binaryToPins() {
  for(int e = 0; e < numBits; e++) {
    //digitalWrite(outputPins[e], masterBinCount[e]); //Записываем наше главное двоичное значение на выходные контакты
    //Serial.print(masterBinCount[e]); //ЭТА СТРОКА ДЛЯ УСТРАНЕНИЯ НЕИСПРАВНОСТЕЙ!!
  }
  isSameVal = true;       //Сообщаем программе, что мы записали на контакты главный счетчик для этого тактового цикла

  outVal = masterCount;

  Serial.println(outVal);
  HWSERIAL.println(outVal);

  //Serial.print(" десятичное: "); //ЭТА СТРОКА ДЛЯ УСТРАНЕНИЯ НЕИСПРАВНОСТЕЙ!!
  //Serial.print(masterCount); //ЭТА СТРОКА ДЛЯ УСТРАНЕНИЯ НЕИСПРАВНОСТЕЙ!!
  //Serial.println(""); //ЭТА СТРОКА ДЛЯ УСТРАНЕНИЯ НЕИСПРАВНОСТЕЙ!!
}

, 👍1

Обсуждение

не имеет отношения к вашей проблеме.... AttachInterrupt() должен быть в setup(), @jsotola


1 ответ


Лучший ответ:

1

Я считаю, что ваша проблема связана с инициализацией HWSERIAL.begin(115200); в void цикле. Чтобы убедиться в этом, я создал этот простой скетч. Во-первых, я закомментировал вторую инициализацию Serial.begin, и вы можете видеть, что я получаю идеальный вывод на последовательный монитор. Затем я раскомментировал строку, повторно загрузил код в Arduino, и вы можете видеть, что он не прошел даже ни одного отпечатка, прежде чем отправил кучу искаженного мусора и фактически заморозил мой последовательный порт.

Удалите HWSERIAL.begin(115200); из void цикла и установите его только в void setup.

Надеюсь, это поможет!

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  Serial.begin(115200);
  Serial.print("Test");
  Serial.print(" - ");
  Serial.println(millis());
}

,

Спасибо! Думаю, это прояснило ситуацию., @Matt