与Arduino进行串行通信的termios结构设置

3
在基于Unix的软件上,需要向Arduino发送0到179之间的数字,并且Arduino将把该数字作为角度应用到舵机上。但我不知道在terminos结构中需要更改哪些参数以允许串行通信。
以下是C++代码:
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <termios.h>

using namespace std;

int main()
{
    unsigned int angle;
    ofstream arduino;
    struct termios ttable;

    //cout<<"test-1";

    arduino.open("/dev/tty.usbmodem3a21");

    //cout<<"test-2";

    if(!arduino)
    {
        cout<<"\n\nERR: could not open port\n\n";
    }
    else
    {

        if(tcgetattr(arduino,&ttable)<0)
        {
            cout<<"\n\nERR: could not get terminal options\n\n";
        }
        else
        {

            //there goes the terminal options setting for the output;

            ttable.c_cflag = -hupcl //to prevent the reset of arduino

            cfsetospeed(&ttable,9600);

            if(tcsetattr(arduino,TCSANOW,&ttable)<0)
            {
                cout<<"\n\nERR: could not set new terminal options\n\n";
            }
            else
            {
                do
                {
                    cout<<"\n\ninsert a number between 0 and 179";
                    cin>>angle;
                    arduino<<angle;
                }while(angle<=179);

                arduino.close();
            }
        }
    }

}

这是Arduino的:

#include <Servo.h>

Servo servo;
const int pinServo = 2;
unsigned int angle;

void setup()
{
    Serial.begin(9600);
    servo.attach(pinServo);

    servo.write(0);

}

void loop()
{
    if(Serial.available()>0)
    {  
       angle = Serial.read();

       if(angle <= 179)
       {
         servo.write(angle);
       }
    }
}

请问您需要修改"ttable"的哪些内容?

2个回答

3
通常,在C/C++中与Arduino通信最简单的方式是使用串口以“原始”模式。这基本上是8N1,逐字节传输,并且TTY会进行最少量的数据处理。在termios结构体中设置此模式中的各个标志的简单方法是使用cfmakeraw(3)。根据man页面,它执行以下操作:
struct termios config;

config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
  INLCR | IGNCR | ICRNL | IXON);
config.c_oflag &= ~OPOST;
config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
config.c_cflag &= ~(CSIZE | PARENB);
config.c_cflag |= CS8;

为了保险起见,使用 config.c_cflag |= (CLOCAL | CREAD); 明确设置接收使能并忽略调制解调控制。如果您使用的 termios 结构体是现有结构体的副本(例如通过 tcgetattr() 获取),则还应将流量控制完全禁用,使用 config.c_iflag &= ~(IXOFF | IXANY);。因此,总体来说代码如下:

struct termios config;

cfmakeraw(&config);
config.c_cflag |= (CLOCAL | CREAD);
config.c_iflag &= ~(IXOFF | IXANY);

// set vtime, vmin, baud rate...
config.c_cc[VMIN] = 0;  // you likely don't want to change this
config.c_cc[VTIME] = 0; // or this

cfsetispeed(&config, B9600);
cfsetospeed(&config, B9600);

// write port configuration to driver
tcsetattr(fd, TCSANOW, &config;

使用C++文件流也有一些棘手的问题。您很可能需要非阻塞读/写且不控制TTY,因此通常最好使用带有O_NOCTTY和O_NDELAY标志设置的open(2)。

1

类似于 termios 的东西是最佳选择

options.c_cflag &= ~CRTSCTS;    
options.c_cflag |= (CLOCAL | CREAD);                   
options.c_iflag |= (IGNPAR | IGNCR);                  
options.c_iflag &= ~(IXON | IXOFF | IXANY);          
options.c_oflag &= ~OPOST;

options.c_cflag &= ~CSIZE;            
options.c_cflag |= CS8;              
options.c_cflag &= ~PARENB;         
options.c_iflag &= ~INPCK;         
options.c_iflag &= ~(ICRNL|IGNCR);
options.c_cflag &= ~CSTOPB;      
options.c_iflag |= INPCK;       
options.c_cc[VTIME] = 0.001;  //  1s=10   0.1s=1 *
options.c_cc[VMIN] = 0;

termiosc_cc 字段是一个 cc_t 数组,该类型在 <bits/termios.h> 中被定义为 unsigned char。因此,对于 c_cc[VTIME] 的浮点值将会被静默转换(除非您向 gcc 传递 -Wconversion,这从来不是一个坏主意)。 - David G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接