没有与连接的串行端口通信?
Posted
技术标签:
【中文标题】没有与连接的串行端口通信?【英文标题】:No communication to a connected serial port? 【发布时间】:2019-01-14 10:37:20 【问题描述】:我正在尝试连接到通过我的基于 Linux 的 PC 中的 USB 串行端口连接的 Arduino Mega 2560 单元。
使用 C 代码,我正在尝试发送和接收简单的文本字符串,只是我能够在双方发送和接收。
在 Arduino 上:
int incomingByte = 0; // for incoming serial data
void setup()
Serial.begin(19200); // opens serial port, sets data rate to 9600 bps
void loop()
// send data only when you receive data:
if (Serial.available() > 0)
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print((char)incomingByte);
基本上只是一个检查是否有串行数据的循环,如果有,则读取并打印回来。有一个 (char) 转换,所以我会立即看到发送的数据就是我返回的数据(Linux 端)
对于 Linux 代码,我使用相当标准的代码来打开我发现的端口 here
我将 Arduino 称为“Table”,因为它最终会通过 USB 命令操作移动的桌子。
C 文件:
#include "TableFunctions.h"
bool connected=false;
int fd;
char *portname;
int set_interface_attribs (int fd, int speed, int parity)
connected=false;
struct termios tty;
struct termios tty_old;
memset(&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
printf("PC: Error %d from tcgetattr \n", errno);
return -1;
tty_old = tty;
cfsetospeed (&tty, (speed_t)B19200);
cfsetispeed (&tty, (speed_t)B19200);
//tty.c_cflag |= B19200;
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; //
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
cfmakeraw(&tty);
tcflush( fd, TCIFLUSH );
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf("PC: Error %d from tcsetattr \n", errno);
return -1;
return 0;
void set_blocking(int fd, int should_block)
struct termios tty;
memset(&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
printf("PC: Error %d from tggetattr \n", errno);
return;
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 10; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf("PC: Error %d setting term attributes \n", errno);
void OpenSerialPort()
char *portname = "/dev/ttyACM0";
printf("PC: Opening port to table \n");
int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
usleep(2000000);
if (fd < 0)
printf("PC: Error %d opening %s: %s \n", errno, portname, strerror(errno));
return;
set_interface_attribs(fd, B19200, 0); // set speed to 19,200 bps, 8n1 (no parity)
set_blocking(fd, 0); // set no blocking
printf("PC: Connected\n");
connected = true;
void PrepareWriteCommand(int numberOfCommands, const char *commands[numberOfCommands])
if(connected) //check if arduino still connected
for(int i = 0; i<numberOfCommands; i++) //go through commands
int bufferSize = strlen(commands[i]); //get the buffer size needed for this command
char charArray[bufferSize]; //helper char array
memcpy(charArray,commands[i],bufferSize);//copy command to the char array
charArray[bufferSize]=0; //make sure there is a stop symbok at the end
WriteSerialPort(charArray); //command is ready to be sent, send it.
int WriteSerialPort(const char *buffer)
printf("PC: Now writing: ");
int n_written = 0; //how many bytes were written
n_written = write(fd, buffer, strlen(buffer)); //write the command and return how many bytes were written
printf("\n");
//check bytes send and return ouput (error, nothing or x bytes sent)
if(n_written<0)
printf("PC: Error %d from %s \n",errno, strerror(errno));
else if(n_written == 0)
printf("PC: Nothing was written \n");
else
printf("PC: Written %i bytes \n", n_written);
int ReadSerialPort(char *buffer, unsigned int buff_size)
//check if arduino still connected
if(connected)
//read the serial data
if(read(fd,buffer,buff_size))
return sizeof(buffer); //return how much bytes were read
else
//else print nothing received
printf("PC: Arduino not Connected (ReadSerialPort) \n");
在OpenSerialPort
我基本上是打开一个新的fd
,然后调用设置通讯设置的函数。
我使用PrepareWriteCommand
确保用户输入的命令带有停止符号,并将它们发送到WriteSerialPort
,我使用write()
并打印发送了多少字节。
H 文件:
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#define MAX_DATA_LENGTH 256
int set_interface_attribs (int fd, int speed, int parity);
void set_blocking(int fd, int should_block);
void OpenSerialPort();
void PrepareWriteCommand(int numberOfCommands, const char *commands[numberOfCommands]);
int WriteSerialPort(const char *buffer);
int ReadSerialPort(char *buffer, unsigned int buff_size);
主要:
#include "TableFunctions.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
char output[MAX_DATA_LENGTH]; //char array to hold arduino output
int received = 0; // check if read() got any bytes
const char* commands[]="test"; //test command
OpenSerialPort(); // open serial port
PrepareWriteCommand((sizeof(commands)/sizeof(commands[1])),commands); //prepare command for sending
usleep(500000); //wait for arduino response
while(true)
received = ReadSerialPort(output,MAX_DATA_LENGTH);//check serial port for response
switch(received)
case -1:
printf("PC: Error %d from %s \n",errno, strerror(errno));
break;
case 0:
printf("PC: Nothing received\n");
usleep(500000);
break;
default:
printf("PC: received %i\n",received); //if yes, how many bytes
printf("PC: %s\n",output); //and what was received
usleep(500000);
return 0; //finish program
我尝试调整 TTY 标志设置,但没有成功。每次我运行 C 代码时,我都会看到 Arduino 重置(在打开新的 fd
后,我给它一些引导加载时间)但两者之间没有通信。
输出:
PC: Opening port to table
PC: Connected
testPC: Now writing:
PC: Written 4 bytes
PC: received 0
PC:
对于理解 C 代码为何无法与 Arduino 通信的任何帮助,我们将不胜感激!
【问题讨论】:
您的received
变量永远不会被分配。此外,您没有正确检查 read()
的返回值:它是读取的字节数或 -1
如果错误。而sizeof(buffer)
将返回指针的大小,而不是数组的大小或读取的字节数。
@rodrigo 谢谢,从未注意到收到未分配。现在 linux 的输入是: PC:收到 8 PC:所以 PC 得到 8 个字节(但发送 4,也许 arduino 设法发送数据两次),但什么也不打印。只是为了确保 read() 将读取的数据放入其参数中的缓冲区,对吗?关于 sizeof - 我看了看,似乎没有什么简单的事情要做:***.com/questions/492384/…
傻我,8个字节是指针的大小,不是吗?
是的,sizeof(pointer)
在 64 位系统中将是 8。 read
将读取的数据放入作为参数传递的数组中,并返回实际读取的字节数。第二个参数是缓冲区的大小,即读取的最大字节数。
【参考方案1】:
问题出在OpenSerialPort()
。我设置了另一个变量fd
,它是本地的,因此具有优先权。然后当OpenSerialPort()
完成时,它被删除,并且全局fd
保持未设置。这就是为什么我无法从 PC 发送任何内容或向 PC 发送任何内容。
谢谢。
【讨论】:
以上是关于没有与连接的串行端口通信?的主要内容,如果未能解决你的问题,请参考以下文章