Почему эта программа на 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.

Может ли кто-нибудь помочь мне понять, почему это не работает?

, 👍3

Обсуждение

Добро пожаловать в Ардуино 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.


2 ответа


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

7

Проблема в вашей программе 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.

,

2
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 == "" никогда не сделает ничего полезного и должна быть перехвачена.

,