无法与已连接的串行端口通信?

时间:2019-01-14 10:37:20

标签: c linux arduino serial-port

我正在尝试连接到基于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);
  }

}

基本上只是一个循环,它检查是否有串行数据,如果有则读取并打印回去。有一个(字符)转换,所以我马上就会看到发送的数据是我返回的(Linux端)

对于Linux代码,我使用相当标准的代码来打开我发现的here

端口

我称Arduino为“桌子”,因为它最终将通过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通信的任何帮助!

1 个答案:

答案 0 :(得分:0)

问题出在OpenSerialPort()中。我设置了另一个局部变量fd,因此具有优先级。然后完成OpenSerialPort()后,将其删除,并且全局fd保持未设置状态。这就是为什么我无法从PC发送任何东西到PC的原因。

谢谢。