Xaver
Xaver

Reputation: 1001

linux c++ serial port echoes output

In my program which sends bytes to a serial port, I receive bytes which I send. I don't want to receive bytes which I send, and I don't know how to do this?

#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/ioctl.h>

int fd;
struct termios tio, old_tio;

time_t SubTime_mSec(timeval val1, timeval val2)
{
    timeval tv;
    if (val1.tv_sec > val2.tv_sec) return (0);
    if (val1.tv_sec == val2.tv_sec)
        if (val1.tv_usec > val2.tv_usec) return (0);
    tv.tv_sec = val2.tv_sec - val1.tv_sec;
    if (val1.tv_usec < val2.tv_usec) {
        tv.tv_usec = val2.tv_usec - val1.tv_usec;
    } else {
        tv.tv_sec --;
        tv.tv_usec = 1000000 + val2.tv_usec - val1.tv_usec;
    }

    return(tv.tv_sec*1000 + tv.tv_usec/1000);
}


void RTUOutMessage(int cnt1, int cnt2)
{
    unsigned char msg[13] = {0x01, 0x10, 0x00, 0x2F, 0x00, 0x02, 0x04, 0x4B, 0x64, 0x3D, 0xD9, 0x36, 0xC6};
    int Len = 13;
    int status, i, j;
    ioctl(fd, TIOCMGET, &status);

    status = status | TIOCM_RTS | TIOCM_DTR;
    ioctl(fd, TIOCMSET, &status);
    write(fd, msg, Len);
    for (j = 0; j < cnt1; j ++)
        for (i = 0; i < cnt2; i ++);
    ioctl(fd, TIOCMGET, &status);
    status &= ~TIOCM_RTS;
    status &= ~TIOCM_DTR;
    ioctl(fd, TIOCMSET, &status);

    timeval start_t, curr_t;
    char Buff[80];
    int l;

    gettimeofday(&start_t, NULL);
    curr_t = start_t;
    while (SubTime_mSec(start_t, curr_t) < 1000) {
        l = read(fd, Buff, 80);
        if (l > 0) {
            printf("BUFFER=");
             for(i = 0; i < l; i++) {
                 printf(" %x", Buff[i]);
             }
             //printf("\n");
        }
        gettimeofday(&curr_t, NULL);
    }
}

void  InitPort(void)
{
    int StopBits = 2;
    if ((fd = open("/dev/ttyAM2", O_RDWR | O_NDELAY)) < 0) {
        printf("Couldn't open //dev//ttyAM2\n");
    }
    tcflush(fd, TCIOFLUSH);
    int n = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, n & ~O_NDELAY);
    tcgetattr(fd, &old_tio);
    tcgetattr(fd, &tio);
    cfsetospeed(&tio, (speed_t)B9600);
    cfsetispeed(&tio, (speed_t)B9600);
    tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
    tio.c_cflag |= CLOCAL | CREAD ;
    tio.c_cflag &= ~OFILL; 
    //parity
    tio.c_cflag &= ~(PARENB | PARODD);
    tio.c_cflag &= ~CRTSCTS;
    if (StopBits == 2) tio.c_cflag |= CSTOPB;
    else tio.c_cflag &= ~CSTOPB;
    tio.c_iflag=IGNBRK;
    tio.c_iflag &= ~(IXON|IXOFF|IXANY);
    tio.c_lflag=0;
    tio.c_oflag=0;
    tio.c_cc[VTIME]=0;
    tio.c_cc[VMIN]=0;
    if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 1 failed\n");

    int mcs=0;
    ioctl(fd, TIOCMGET, &mcs);
    mcs |= TIOCM_RTS;
    ioctl(fd, TIOCMSET, &mcs);

    if (tcgetattr(fd, &tio)!=0) printf("tcgetattr() 4 failed\n");
    tio.c_cflag &= ~CRTSCTS;
    if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 2 failed\n");
}

int main(int argc, char **argv)
{
    InitPort();
    int cnt1, cnt2;
    cnt1 = 3;
    cnt2 = 20000;
    cnt1 = atoi(argv[1]);
    cnt2 = atoi(argv[2]);
    for(;;) {
    RTUOutMessage(cnt1, cnt2);
    usleep(1000000);
    }
    tcsetattr(fd, TCSANOW, &old_tio);
    close(fd);
    printf("End\n");

    return 0;
}

Upvotes: 4

Views: 3897

Answers (1)

sawdust
sawdust

Reputation: 17047

If you are receiving the chars that you sent, then the remote's serial port is apparently echoing its input.

You will either have to disable input echo at the other device, or perform "echo cancellation" in your receive logic. I.E. create an "echo FIFO". Each byte output to the serial port is also written to the "echo FIFO". Set a flag indicating that an echo is expected. As input is received, compare it to the "echo FIFO", and remove chars when it matches, and toss the receive char. If no match, then accept receive char. Clear the echo flag when the "echo FIFO" is empty.

BTW the code appears to set the serial port to raw or non-canonical mode. The preferred method would be to use

cfmakeraw(&tio);

rather than

tio.c_iflag=IGNBRK;
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
tio.c_lflag=0;
tio.c_oflag=0;

Upvotes: 4

Related Questions