Почему эта программа на C++ не может прочитать Serial.write() моего arduino?
Я сделал очень простой скетч Arduino Uno для отправки последовательного байта раз в секунду:
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(12); // отправляем байт со значением 12
delay(1000);
}
Мой arduino подключен к com 3.
На другом конце линии у меня есть программа на C++ со следующей функцией чтения:
int Serial::ReadData(char *buffer, unsigned int nbChar)
{
//Количество байтов, которое мы прочитаем
DWORD bytesRead;
//Количество байтов, которое мы действительно попросим прочитать
unsigned int toRead;
//Используем функцию ClearCommError для получения информации о статусе последовательного порта
ClearCommError(this->hSerial, &this->errors, &this->status);
//Проверяем, есть ли что прочитать
if(this->status.cbInQue>0)
{
//Если есть, проверяем, достаточно ли данных для чтения нужного числа
// символов, если нет, мы будем читать только доступные символы, чтобы предотвратить
// блокировка приложения.
if(this->status.cbInQue>nbChar)
{
toRead = nbChar;
}
else
{
toRead = this->status.cbInQue;
}
// Попытаться прочитать требуемое количество символов и вернуть количество прочитанных байтов в случае успеха
if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
{
return bytesRead;
}
}
//Если ничего не было прочитано или обнаружена ошибка, возвращаем -1
return -1;
}
Похоже, что это проверяет только один раз, доступны ли данные, поэтому, очевидно, мне приходится перебирать их, пока не поступят данные. Я сделал это в своей основной программе:
#include "Serial.h"
#include <iostream>
using namespace std;
int main(void)
{
Serial serial("COM3");
char* c = "";
int len = strlen(c);
while(c == "")
{
serial.ReadData(c, len);
}
cout << "\n\n";
system("PAUSE");
}
Когда я это делаю, моя программа на C++ застревает в бесконечном цикле ожидания данных от Arduino, и я не могу понять, почему это происходит. Моя программа никогда не видит данные, которые отправляет Arduino.
Этот класс Serial работает и настроен правильно, потому что я могу без проблем ОТПРАВИТЬ все данные, которые хочу, на Arduino. У меня проблемы только с чтением с Arduino.
Может ли кто-нибудь помочь мне понять, почему это не работает?
@xcdemon05, 👍3
Обсуждение2 ответа
Лучший ответ:
Проблема в вашей программе C++ на другом конце линии (не на стороне Arduino):
char* c = "";
int len = strlen(c);
while(c == "")
{
serial.ReadData(c, len);
}
Здесь len
равно нулю, потому что это длина "" , пустой строки! Таким образом, в вашем цикле вы просите ReadData
прочитать 0 байтов. Следовательно, условие вашего цикла while
всегда истинно, поскольку c
никогда не меняется.
Кроме того, условие while
кажется неверным, так как в C++ не рекомендуется сравнивать 2 строки (определяется как char *
или char [...]
) с ==
. В вашей ситуации важно количество символов, прочитанных ReadData
:
char c[LEN + 1];
int numBytes = 0;
while(true)
{
numBytes = serial.ReadData(c, LEN);
if (numBytes != -1)
{
// Завершить строку, если мы хотим использовать переменную c как строку
c[numBytes] = 0;
break;
}
}
в приведенном выше коде LEN
— это количество символов, которое вы хотите прочитать за один раз, в вашем примере оно должно быть установлено равным 1, либо как #define
или как переменная const
:
// либо:
#define LEN 1
// или:
const int LEN = 1;
Приведенный выше код также гарантирует, что c
может использоваться как обычная строка, путем добавления 0
в конце. Это обязательно, только если вы хотите использовать строковые функции в c
, такие как strlen
, strcpy
, strchr
.. . в противном случае numBytes
достаточно для управления количеством символов, прочитанных в c
.
char* c = "";
while(c == "")
Неправильное название переменной c, поскольку это указатель на строку, а не на символ. Например, c = 0x123456.
Вы должны использовать более явное имя для вашей переменной.
Эта первая строка присваивает указатель на пустую строку указателю c. Итак, значение, хранящееся по адресу 0x123456 == любой указатель на статический адрес памяти, содержащий '\0'
Обратите внимание, что для хранения символов не выделена память. Выделен только указатель на char. Таким образом, вы не можете ничего хранить в своей строке!!
Вы можете написать что-то вроде:
char data[2] = "";
Это выделило бы указатель и строку для хранения 2 символов
Вторая строка, while(c == "")
, сравнивает реальный указатель памяти (например, 0x123456) с указателем компилятора.
""
не является настоящим указателем приложения, им не следует манипулировать.
Поэтому вторая строка зависит от поведения компилятора.
На вашем месте я бы превратил многосимвольную процедуру в односимвольную. Например:
int ReadChar(char *c)
{
return ReadData(c, 1);
}
Затем:
main()
{
char c;
ReadChar(&c);
}
С другой стороны, я думаю, что компилятор должен ловить такую ошибку.
Строка c == ""
никогда не сделает ничего полезного и должна быть перехвачена.
- Как изменить переменную при нажатии кнопки, подключенной к контакту 2
- Как напечатать несколько номеров через Serial с очень небольшим количеством строк кода?
- Последовательная связь Arduino с Arduino без библиотеки
- Акцептант векселей ИКТ
- Проблема с массивом + последовательным монитором
- Arduino wrap или подкласс print() для работы с несколькими Serial
- Матричный дисплей с Arduino UNO (ПРОБЛЕМА)
- Проверка входной строки последовательной связи Arduino
Добро пожаловать в Ардуино SE! Вы проверили, что код Arduino выводит правильные данные с последовательным монитором? Если это так, я думаю, что этот вопрос следует перенести на другой сайт для решения кода C++. Спасибо!, @Anonymous Penguin
Можете ли вы также подтвердить, что программа-приемник работает, если вы отправляете некоторые «правильные» данные с помощью терминальной программы? Ответы на эти два вопроса подскажут вам, следует ли смотреть на Arduino, принимающий процессор или последовательную линию., @JRobert
Я хочу отправить данные клавиатуры из Arduino в Code Composer Studio или CCS, и я использую инструменты Texas (TMS320F8069). Когда я отправлю данные, я надеюсь, что CCS покажет данные Arduino, которые я уже отправил. И CCS отправит его обратно. Это похоже на программу TR > RX. Но это не работа. Я имею в виду, что консоль CCS (последовательный монитор) не показывает данные. Итак, вы, ребята, можете помочь мне решить эту проблему? Вот мой код CCS... const int LEN = 1; char msgg[LEN + 1]; число байт = 0; for(;;) { msgg [numBytes] = 0; scia_msg (сообщение); // Ожидание символа inc while(SciaRegs.SCIFFRX.bit.RXFFST !=1) { } // ожидание XRDY, @Amirullah S.