#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)
.