Полудуплексный RS485 linux последовательное программирование USB на C

#c #linux #ubuntu #serial-port #rs485

#c #linux #ubuntu #последовательный порт #rs485

Вопрос:

Я пытаюсь настроить полудуплексную связь в Ubuntu 14.04 в своей программе. У меня есть приемопередатчик RS485, использующий линию RTS для переключения между передачей и приемом. Я использую speak, когда говорю с системой, и эта программа является ведущей. Проблема в том, что RTS не отключается, когда я заканчиваю отправку пакета, чтобы я мог получить данные. По сути, я хочу, чтобы он увеличивал RTS, отправлял данные, уменьшал RTS, а затем считывал данные. Любая помощь была бы отличной.

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <sys/types.h>

#define BAUDRATE B38400
#define COMPORT "/dev/ttyUSB0"
#define _POSIX_SOURCE 1
#define FALSE 0
#define TRUE 1

#define STX_KEYPAD 0xE1
#define PAYLOAD_BUFF_SIZE 256

#define CRC_HI 0xD8
#define CRC_LOW 0xC3

volatile int STOP=FALSE;

int ser_port;
int bus_address = 1;
int message_length = 0;
struct termios oldtio,newtio;
unsigned char rxbuf[256];
unsigned char tx_flags = 0;

void openCommPort();
void sendSerial();
int setRTS(int level);

int main(void)
{
     printf("Starting...rn");
 openCommPort();
 setRTS(1);
 printf("Sending Serial Datarn");
 sendSerial();
 setRTS(0);
 //close(ser_port);
 printf("All Donern");

     return EXIT_SUCCESS;
}

void openCommPort()
{
   ser_port = open(COMPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
   if (ser_port == -1)
    {
       perror(COMPORT);
       perror("Unable to open port");
       exit(-1);
    }

   if(tcgetattr(ser_port,amp;oldtio) <0)// save current port settings
    {
       perror(COMPORT);
       perror("Couldn't get old terminal attributes");
       exit (-1);
    }

    bzero(amp;newtio, sizeof(newtio));

    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | CRTSCTS;     

     newtio.c_iflag = IGNPAR | ICANON;

    newtio.c_oflag = 0;

       // set input mode (non-C, no echo,...)
   newtio.c_lflag = 0;

   newtio.c_cc[VTIME]    = 0;   // inter-character timer unused
   newtio.c_cc[VMIN]     = 0;   // blocking read until 5 chars received

   tcflush(ser_port, TCIFLUSH);
   tcsetattr(ser_port,TCSANOW,amp;newtio);
 }

void sendSerial()
{
unsigned char tx_header[6];

tx_header[0] = STX_KEYPAD;
tx_header[1] = bus_address;
tx_header[2] = tx_flags;
tx_header[3] = message_length;
tx_header[4] = CRC_HI;
tx_header[5] = CRC_LOW;

if((write(ser_port, tx_header, 6)) != 6)
 {
     printf("Error sending data!  Not all bytes sentrn");
 }

}

int setRTS(int level)
{
int status;

 if (ioctl(ser_port, TIOCMGET, amp;status) == -1)
    {
        perror("getRTS(): TIOCMSET");
        return 0;
    }


if(level)
 {
     status |= TIOCM_RTS;
 }
 else
 {
    status amp;= ~TIOCM_RTS;
 }

if (ioctl(ser_port, TIOCMSET, amp;status) == -1)
{
    perror("setRTS(): TIOCMSET");
    return 0;
}

return 1;
}
 

Комментарии:

1. Может быть, я этого не понимаю, но… почему вы используете TIOCM_DTR вместо TIOCM_RTS , если функция названа setRTS() ?

2. Опечатка с моей стороны, которую я использовал TIOCM_RTS , а не TIOCM_DTR . Я обновил приведенный выше код, чтобы правильно отразить код.

3. Код sendSerial(); setRTS(0); не гарантирует передачу данных перед вызовом setRTS(0) . Он только направляет код для начала отправки сообщения. Завершение произойдет позже. Коду нужен вызов какой-либо функции TBD, подобной fflush() той, которая гарантирует, что исходящий буфер пуст, затем вызовите setRTS(0) .