C ++ Последовательное общение чтение данных работает, но запись не удается - PullRequest
0 голосов
/ 27 ноября 2018

Я создаю класс для последовательной связи между встроенной системой и приложением C ++, работающим в среде Linux.Поэтому я использовал термин API для Linux, который описан здесь .

Конструктор откроет последовательный порт устройства.В моем случае это 'ttyUSB0' для микроконтроллера Arduino, который я использовал.Затем он установит скорость передачи и другие параметры порта.

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

После выполнения тестового задания чтение, похоже, работало нормально.Функция «Available ()» действительно возвращает количество байтов, которые доступны.Они выводятся на консоль после их прочтения.

Однако по неизвестной причине моя функция записи не работает, хотя я «верю», что правильно выполнил шаги из руководства.Я сделал тест-кейс для функции записи: arduino должен мигать своим встроенным светодиодом, как только получит правильное сообщение.Сообщение является правильным, когда оно начинается с начального знака «#» и заканчивается конечным знаком «$».

Когда я отправляю правильное сообщение с замазкой инструмента тестирования или с серийным монитором arduino, светодиод будет мигать.Но этого не происходит, когда я отправляю сообщение через собственную функцию записи.

Arduino имеет другие встроенные светодиоды, которые показывают данные на выводах RX и TX.Эти светодиоды на самом деле загораются, когда я отправляю данные из своей собственной функции записи, но функция blink в моем тестовом случае никогда не вызывается.Затем я проверил, были ли вообще прочитаны какие-либо байты, но Arduino 'Serial.available ()' никогда не возвращает значение больше 0, когда данные отправляются из моей собственной функции записи.

Я думаю, что ошибкалибо в самой функции записи, либо в конфигурации последовательного порта.Так далеко, я не могу понять это.Кто-нибудь имеет какой-либо опыт или знания по этому поводу или есть какие-либо советы о том, как мне следует решить эту проблему?

Заранее спасибо,

Dirk

Код Linux:

main.cpp

#include "serial.h"
#include <iostream>

using namespace std;

int main()
{
    //TEST CASE FOR WRITING DATA
    Serial serial("/dev/ttyUSB0");
    serial.Write("#TEST$"); 

    //TEST CASE FOR READING DATA
    /*while (true)
    {
        char message[100];
        char * ptr = NULL;
        while (serial.Available() > 0)
        {
            char c; 
            serial.Read(&c);
            switch(c)
            {
            case '#':
                ptr = message;
                break;
            case '$':
                if (ptr != NULL)
                {
                    *ptr = '\0';
                }
                std::cout << "received: " << message << std::endl;
                ptr = NULL;
                break;
            default:
                 if (ptr != NULL)
                {
                    *ptr = c;
                    ptr++;
                }
                break;
            }
        }
    }*/
    return EXIT_SUCCESS;
}

Serial.h

#ifndef SERIAL_H
#define SERIAL_H

#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <string>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>

class Serial
{
    private:
        int fd;
    public:
        Serial(std::string device);

        ~Serial()
        {
            close(fd);
        };     

        int Available();
        void Read(char * buffer, int amountOfBytes);
        void Read(char * bytePtr);
        int Write(std::string message);
};

#endif

Serial.cpp

#include "serial.h"
#include <stdexcept>
#include <string.h>

Serial::Serial(std::string device)
{   
    // Open port
    fd = open(device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0)
    {
        throw std::runtime_error("Failed to open port!");
    }

    // Config
    struct termios config;

    tcgetattr(fd, &config);

    // Set baudrate
    cfsetispeed(&config, B9600);
    cfsetospeed(&config, B9600);

    // 9600 8N1
    config.c_cflag &= ~PARENB;
    config.c_cflag &= ~CSTOPB;
    config.c_cflag &= ~CSIZE;
    config.c_cflag |=  CS8;

    // Disable hardware based flow control
    config.c_cflag &= ~CRTSCTS;

    // Enable receiver
    config.c_cflag |= CREAD | CLOCAL;                               

    // Disable software based flow control
    config.c_iflag &= ~(IXON | IXOFF | IXANY);

    // Termois Non Cannoincal Mode 
    config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 

    // Minimum number of characters for non cannoincal read
    config.c_cc[VMIN]  = 1;

    // Timeout in deciseconds for read
    config.c_cc[VTIME] = 0; 

    // Save config
    if (tcsetattr(fd, TCSANOW, &config) < 0)                        
    {
        close(fd);
        throw std::runtime_error("Failed to configure port!");
    }

    // Flush RX Buffer
    if (tcflush(fd, TCIFLUSH) < 0)
    {
        close(fd);
        throw std::runtime_error("Failed to flush buffer!");
    }
}

int Serial::Available()
{
    int bytes = 0;
    if (ioctl(fd, TIOCINQ, &bytes) < 0)
    {
        close(fd);
        throw std::runtime_error("Failed to check buffer!");
    }
    return bytes;
}

void Serial::Read(char * buffer, int amountOfBytes)
{
    if (read(fd, buffer, amountOfBytes) < 0)
    {
        close(fd);
        throw std::runtime_error("Failed to read bytes!");
    }
}

void Serial::Read(char * bytePtr)
{
    return Serial::Read(bytePtr, 1);
}

int Serial::Write(std::string message)
{
    int length = message.size();
    if (length > 100)
    {
        throw std::invalid_argument("Message may not be longer than 100 bytes!");
    }

    char msg[101];
    strcpy(msg, message.c_str());

    int bytesWritten = write(fd, msg, length);

    if (bytesWritten < 0)
    {
        close(fd);
        throw std::runtime_error("Failed to write bytes!");
    }

    return bytesWritten;
}

Код Arduino

void setup() 
{
    Serial.begin(9600);
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop() 
{
    //TEST-CASE FOR WRITING DATA
    /*Serial.print("#TEST$");
    delay(1000);*/

    //TEST-CASE FOR READING DATA
    char message[100];
    char * ptr = NULL;
    while (Serial.available() > 0)
    {
        char c = Serial.read();
        switch(c)
        {
        case '#':
            ptr = message;
            break;
        case '$':
            if (ptr != NULL)
            {
                *ptr = '\0';
            }
            ptr = NULL;
            int messageLength = strlen(message);
            Blink();
            break;
        default:
            if (ptr != NULL)
            {
              *ptr = c;
              ptr++;
            }
            break;
        }
    }
}

void Blink()
{
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
}

1 Ответ

0 голосов
/ 04 декабря 2018

решаемая.Функция «open» посылает сигнал на последовательный порт, который arduino интерпретирует как сигнал для перезагрузки.Я исправил проблему с помощью , отключив автоматический сброс .

В качестве альтернативы вы можете добавить две секунды задержки после сохранения конфигурации.

Эта проблема касается только микроконтроллеров Arduino.

...