Arduino至Linux(RPi)串行代码混乱

时间:2019-04-28 23:20:22

标签: c++ raspberry-pi serial-port uart

我目前正在使用GitHub上出色的hoverboard-firmware-hack源代码,它的确很棒。我目前正在使用UART协议,因此可以通过串行UART与Hoverboard主板进行通讯。主机慷慨地提供了一些arduino示例代码,以使用自定义固件协议发送基本命令:

SoftwareSerial mySerial(10, 11); // RX, TX

typedef struct MsgToHoverboard_t{
  unsigned char SOM;  // 0x02
  unsigned char len;  // len is len of ALL bytes to follow, including CS
  unsigned char cmd;  // 'W'
  unsigned char code; // code of value to write
  int16_t base_pwm;   // absolute value ranging from -1000 to 1000 .. base_pwm plus/minus steer is the raw PWM value
  int16_t steer;      // absolute value ranging from -1000 to 1000 .. wether steer is added or substracted depends on the side R/L
  unsigned char CS;   // checksumm
};

uint16_t baseSpeed = 0;

typedef union UART_Packet_t{
  MsgToHoverboard_t msgToHover;
  byte UART_Packet[sizeof(MsgToHoverboard_t)];
};

void setHoverboardPWM( int16_t base_pwm, int16_t steer )
{
  UART_Packet_t ups;

  ups.msgToHover.SOM = 2 ;  // PROTOCOL_SOM; //Start of Message;
  ups.msgToHover.len = 7;   // payload + SC only
  ups.msgToHover.cmd  = 'W'; // PROTOCOL_CMD_WRITEVAL;  // Write value
  ups.msgToHover.code = 0x07; // speed data from params array
  ups.msgToHover.base_pwm = base_pwm;
  ups.msgToHover.steer = steer;
  ups.msgToHover.CS = 0;

  for (int i = 0; i < ups.msgToHover.len; i++){
    ups.msgToHover.CS -= ups.UART_Packet[i+1];
  }

  mySerial.write(ups.UART_Packet,sizeof(UART_Packet_t));
}

这非常好!我目前正在尝试在RPi上执行此操作,并且不会太遥远,因为Python可能会令人困惑,因为它的类型不是很严格,因此字节大小可能很难指定。

我尝试使用termios在C ++中做到这一点,但并没有走得太远。功能如下:

//Hover couch Serial test

#include <cstdint>
#include <iostream>
#include <stdio.h>
#include <unistd.h>  //Used for UART
#include <fcntl.h>   //Used for UART
#include <termios.h> //Used for UART

using namespace std;

typedef struct MsgToHoverboard_t
{
    unsigned char SOM;  // 0x02
    unsigned char len;  // len is len of ALL bytes to follow, including CS
    unsigned char cmd;  // 'W'
    unsigned char code; // code of value to write
    int16_t base_pwm;   // absolute value ranging from -1000 to 1000 .. base_pwm plus/minus steer is the raw PWM value
    int16_t steer;      // absolute value ranging from -1000 to 1000 .. wether steer is added or substracted depends on the side R/L
    unsigned char CS;   // checksumm
} MsgToHoverboard_t;

uint16_t baseSpeed = 0;

typedef union UART_Packet_t {
    MsgToHoverboard_t msgToHover;
    uint8_t UART_Packet[sizeof(MsgToHoverboard_t)];
} UART_Packet_t;

void setHoverboardPWM(int16_t base_pwm, int16_t steer, int &handle)
{
    UART_Packet_t ups;

    ups.msgToHover.SOM = 2;     // PROTOCOL_SOM; //Start of Message;
    ups.msgToHover.len = 7;     // payload + SC only
    ups.msgToHover.cmd = 'W';   // PROTOCOL_CMD_WRITEVAL;  // Write value
    ups.msgToHover.code = 0x07; // speed data from params array
    ups.msgToHover.base_pwm = base_pwm;
    ups.msgToHover.steer = steer;
    ups.msgToHover.CS = 0;

    for (int i = 0; i < ups.msgToHover.len; i++)
    {
        ups.msgToHover.CS -= ups.UART_Packet[i + 1];
    }

    //   mySerial.write(ups.UART_Packet,sizeof(UART_Packet_t));
    if (handle != -1)
    {
        int count = write(handle, &ups.UART_Packet, sizeof(UART_Packet_t)); //Filestream, bytes to write, number of bytes to write
        // cout << "count: " << count << endl;
        if (count < 0)
        {
            printf("UART TX error\n");
        }
    }
}

int main()
{

    //-------------------------
    //----- SETUP USART 0 -----
    //-------------------------
    //At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
    int uart0_filestream = -1;

    //OPEN THE UART
    //The flags (defined in fcntl.h):
    //  Access modes (use 1 of these):
    //      O_RDONLY - Open for reading only.
    //      O_RDWR - Open for reading and writing.
    //      O_WRONLY - Open for writing only.
    //
    //  O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
    //                                          if there is no input immediately available (instead of blocking). Likewise, write requests can also return
    //                                          immediately with a failure status if the output can't be written immediately.
    //
    //  O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
    uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
    if (uart0_filestream == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
        printf("Error - Unable to open UART.  Ensure it is not in use by another application\n");
    }

    //CONFIGURE THE UART
    //The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
    //  Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
    //  CSIZE:- CS5, CS6, CS7, CS8
    //  CLOCAL - Ignore modem status lines
    //  CREAD - Enable receiver
    //  IGNPAR = Ignore characters with parity errors
    //  ICRNL - Map CR to NL on input (Use for ASCII comms where you want to auto correct end of line characters - don't use for bianry comms!)
    //  PARENB - Parity enable
    //  PARODD - Odd parity (else even)
    struct termios options;
    tcgetattr(uart0_filestream, &options);
    options.c_cflag = B19200 | CS8 | CLOCAL | CREAD; //<Set baud rate
    options.c_iflag = IGNPAR;
    options.c_oflag = 0;
    options.c_lflag = 0;
    tcflush(uart0_filestream, TCIFLUSH);
    tcsetattr(uart0_filestream, TCSANOW, &options);

    cout << "Beginning serial output\n";
    while (1)
    {
        setHoverboardPWM(200, 0, uart0_filestream);
    }

    //----- CLOSE THE UART -----
    close(uart0_filestream);
    return 0;
}

这在很大程度上是借来的代码。我尽力使它工作。但是,我遇到了大量“ UART TX error!”(来自SetHoverBoard PWM内部)。我对UART通信协议不是非常有经验,但是我知道我的波特率是正确的,并且串行端口可以工作。我只是在打包错误?

经验丰富的人可以协助我以python方式重新生成此代码或修复当前的c ++代码吗?

我还将提供我处理过的TX示例代码,以防万一我搞砸了:

代码链接:https://raspberry-projects.com/pi/programming-in-c/uart-serial-port/using-the-uart

代码本身:

    //----- TX BYTES -----
    unsigned char tx_buffer[20];
    unsigned char *p_tx_buffer;

    p_tx_buffer = &tx_buffer[0];
    *p_tx_buffer++ = 'H';
    *p_tx_buffer++ = 'e';
    *p_tx_buffer++ = 'l';
    *p_tx_buffer++ = 'l';
    *p_tx_buffer++ = 'o';

    if (uart0_filestream != -1)
    {
        int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0]));      //Filestream, bytes to write, number of bytes to write
        if (count < 0)
        {
            printf("UART TX error\n");
        }
    }

我假设位奇偶校验,一切都很好。似乎设置匹配。

0 个答案:

没有答案