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(""); //ЭТА СТРОКА ДЛЯ УСТРАНЕНИЯ НЕИСПРАВНОСТЕЙ!!
}
@Matt, 👍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
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- В чем разница между Serial.write и Serial.print? И когда они используются?
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Программы построения последовательных данных
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Очистить существующий массив при получении новой последовательной команды
не имеет отношения к вашей проблеме.... AttachInterrupt() должен быть в setup(), @jsotola