gpt4 book ai didi

linux - C++串口通信读数据有效但写入失败

转载 作者:太空宇宙 更新时间:2023-11-04 11:58:11 29 4
gpt4 key购买 nike

我正在为嵌入式系统和在 Linux 环境中运行的 C++ 应用程序之间的串行通信创建一个类。因此我使用了用于 Linux 的 termios API,描述为 here .

构造函数将打开设备的串口。在我的例子中,我使用的 arduino 微 Controller 是“ttyUSB0”。接下来它将设置波特率和其他端口选项。

我还添加了在串口上读取或写入数据的函数。因为 read 是一个阻塞函数(直到接收到数据或超时才返回),我添加了一个函数来检查是否有可用字节,您可以在调用“Read()”之前执行此操作。

制作测试用例后,阅读似乎工作正常。函数“Available()”确实会返回可用的字节数。阅读后将它们打印到控制台。

然而,由于某些未知原因,我的写入功能无法正常工作,即使我“相信”我已正确遵循指南中的步骤。我为写入功能做了一个测试用例:一旦收到正确的消息,arduino 应该闪烁它的内置 LED。以开始标记“#”开始并以结束标记“$”结束的消息是正确的。

当我使用测试工具 putty 或使用 arduino 的串行监视器发送正确的消息时,led 会闪烁。但是当我通过我自己的写函数发送消息时,这不会发生。

arduino 还有其他内置 LED,用于指示 RX 和 TX 引脚上的数据。一旦我从我自己的写入函数发送数据,这些 LED 实际上会亮起,但我的测试用例中的闪烁函数从未被调用。然后我检查是否读取了任何字节,但是当从我自己的写入函数发送数据时,arduino 的“Serial.available()”从不返回高于 0 的值。

我认为错误要么在写入函数本身,要么在串行端口的配置中。到目前为止,我无法弄清楚这一点。有没有人对此有任何经验或知识,或者对我应该如何解决这个问题有任何提示?

提前致谢

德克

Linux 代码:

主要.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;
}

序列号.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

串口.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);
}

最佳答案

已解决。“打开”功能在串行端口上发送信号,arduino 将其解释为重启信号。我通过 disabling auto-reset 解决了这个问题.

或者,您可以在保存配置后添加两秒的延迟。

这个问题特别适用于 arduino 微 Controller 。

关于linux - C++串口通信读数据有效但写入失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53508059/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com