0
\$\begingroup\$

I have written a program which can send and then receive the message just sent from the UART port and I have connected the TXD to RXD together of the same UART port. It has three parts, which are the main function, the function used to open the UART device and the function used to set features of the device. the code are as follows: The main function:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
/********************************************************************
       This app can open a serial device which is the first parameter 
delivered to the main function,
and send a string, then, receive it.
version: 1.3

*******************************************************************/








int open_uart(char* port_name);
int UART_initialize(int fd, speed_t speed, int flow_ctrl, int 
data_bits, int stop_bits, int parity );



int main(int argc, char*argv[])
{
    int fd;
    char rev_buff[1023];//read
    char send_buff[1023];//write
    char flag='y';
    int rev_len;
    int send_len;
    fd= open_uart(argv[1]);
    if(fd == 0)
    {
        fprintf(stderr,"open serial terminal failed...\n");
        return -1;
    }

    tcflush(fd,TCIOFLUSH);

    UART_initialize(fd,B115200,0,8,1,2);
    while(flag=='y'||flag=='Y')
    {
        printf("Please type in the charactors you want to send~\t:");
        scanf("%s",send_buff);
        fflush(stdin);
        send_len=write(fd,send_buff,strlen(send_buff)+1);
        if(send_len<0)
        {
            fprintf(stderr,"send failed!\n");
            send_buff[0]='\0';
            continue;
        }
        printf("you have sent:\t%s(%dbytes)\n",send_buff,send_len);
        send_buff[0]='\0';
        tcflush(fd,TCOFLUSH);
        printf("start receive\n");


        rev_len=read(fd,rev_buff,1024);
        tcflush(fd,TCIFLUSH);
        if(rev_len<0)
        {
            fprintf(stderr,"receive failed");
            rev_buff[0]='\0';
        }
        else if (rev_len==0)
        {
            fprintf(stderr,"the port doesn't received any data!\n");
        }

        else
        {
            printf("you have received:%s\n(%dbytes)",rev_buff,rev_len);
        }
        printf("Do you want to continue?(y/n):");
        scanf("%c",&flag);
        fflush(stdin);
        getchar();  
    }
    close(fd);
}

The function used to open the device:

/******************************open the 
terminal***********************************
name:   open_uart   
input:  char* port_name: the path to the serial device.
output: file descripter: fd ------> the termianl device.
********************************************************************/
int open_uart(char* port_name)
{
    int fd;//the number standing for the uart port
    //did I open the device successfully 
    fd=open(port_name, O_RDWR|O_NOCTTY|O_NDELAY);//not block
    if(fd == -1)
    {
        printf("can't open the tty port!\n");
        return 0;
    }
    //whether the device is blocked
    if(fcntl(fd, F_SETFL, 0) <0)
    {
        printf("fcntl failed!\n");
        return(0);
    }     
    else
    {
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    }
    //whether the device is a tty?
    if(isatty(fileno(stdin))==0)
    {
        printf("standard input is not a terminal device\n");
        return(0);
    }
    else
    {
        printf("the stnadard input is a  tty!\n");

    }
    printf("fd->tty_device=%d\n",fd);
    return fd;
}
/*********************************************************/

The function used to set the features of the device

/***********************************************************
name:       UART_initialize
function:   set the number of bits in one data unit, the stoping bit 
and the 
    verifying bit
input:      fd(int): the file descripter pointing to the device
            speed(speed_t):the speed of the termianl
            flow_ctrl: RTS\CTS
            data_bits: the number of the bits in a data unit 7 or 8
            stop_bits: 
            parity:    verifying type
output:     successful: 1   unsuccessful:0


*************************************************/

int UART_initialize(int fd, speed_t speed, int flow_ctrl, int 
data_bits, int stop_bits, int parity)
***************************************
{
    struct termios options;
    if(tcgetattr(fd,&options))
    {
        perror("SetupSerial 1");
        return(0);
    }
    //set bps
    cfsetispeed(&options, speed);
    cfsetospeed(&options, speed);

    ///////

    options.c_cflag |= CLOCAL;

    options.c_cflag |= CREAD;

    switch(flow_ctrl)
    {

        case 0 ://不使用流控制
        options.c_cflag &= ~CRTSCTS;break;
        case 1 ://使用硬件流控制
        options.c_cflag |= CRTSCTS;break;
        case 2 ://使用软件流控制
        options.c_cflag |= IXON | IXOFF | IXANY;break;
     }

    //set the number of bits
    options.c_cflag &= ~CSIZE;//reset the bits mark bits except the 
former ones
    switch(data_bits)
    {
        case 5: options.c_cflag |= CS5;break;
        case 6: options.c_cflag |= CS6;break;
        case 7: options.c_cflag |= CS7;break;
        case 8: options.c_cflag |= CS8;break;
        default: fprintf(stderr,"Unsupported data size\n");
        return 0;
    }   
    //parity bit
    switch(parity)
    {
        case 0:// no parity bit 
            options.c_cflag &=~PARENB;
            options.c_cflag &=~INPCK;
            break;
        case 1://odd number
            options.c_cflag |=(PARODD|PARENB);
            options.c_cflag |=INPCK;
            break;
        case 2://even number
            options.c_cflag |=(PARENB|INPCK);
            options.c_cflag &=~PARODD;
            break;

    } 
    switch(stop_bits)
    {
        case 1://1 stop bit
            options.c_cflag &=~CSTOPB;
            break;
        case 2://2 stop bits
            options.c_cflag |=CSTOPB;
            break;
        default:
           fprintf(stderr,"Unsupported stop bits\n");
           return(0);
    }
    //close special output mode
    options.c_oflag &= ~OPOST;

    //input mode
    options.c_iflag &=~BRKINT;
    options.c_iflag &=~IGNBRK;//break until NULL

    //wait time and minmum number of "bytes"
    options.c_cc[VTIME]= 1;//wait for 0.1s
    options.c_cc[VMIN]= 1;//read at least 1 byte
    //if flush, receive the data do not read
    tcflush(fd,TCIFLUSH);

    //set options
    if(tcsetattr(fd,TCSANOW,&options)!=0)
    {
        perror("tty set error!\n");
        return 0;
    }
    return 1;
}

The problem I encountered is that I type a short string into the cmd line, such as "Hello!", the program seemed to "stop" after printing start receiving with the indicator led of txd and rxd keep giving out light. I suppose the device send the string repeatedly. But what exactly cause the problem? Can you help me?


Here is my two attempt with the program. In the first attempt, I connect the RXD and TXD together, while in the second attempt I didn't connected them just leaving them suspended. Here is my command line: enter image description here The two attempt both paused at the same place. However, in the first attempt, the sending and receiving LEDs kept being lit up,like this: enter image description here

while the LEDs were off after a short lit. Besides, I used oscilloscope and found that in the first attempt, the TXD keeps sending data, while in the second attempt, the TXD just send a very short piece of data then send nothing.

\$\endgroup\$

closed as off-topic by PeterJ, brhans, Dmitry Grigoryev, Voltage Spike, Dave Tweed Sep 15 '17 at 12:31

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions on the use of electronic devices are off-topic as this site is intended specifically for questions on electronics design." – PeterJ, brhans, Voltage Spike, Dave Tweed
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    \$\begingroup\$ Do you have an oscilloscope? What are these LEDs actually indicating? Maybe the UART LEDs are not "activity" LEDs but only indicate the state of the line. \$\endgroup\$ – Spehro Pefhany Sep 9 '17 at 14:05
  • 1
    \$\begingroup\$ @brhans - the code is not dealing with a UART directly, it is dealing with a Serial Port buffered by the operating system, so your comment isn't really accurate. \$\endgroup\$ – Chris Stratton Sep 9 '17 at 18:02
  • 3
    \$\begingroup\$ The use of tcflush(fd,TCOFLUSH) seems inappropriate - unlike Arduino Serial.flush() this discards rather than waits and you haven't allowed time for the message to be transmitted at the serial baud rate, which is far slower than a few lines of code and a printf(). That said, I'm very tempted to vote to close this as off topic as it's really about POSIX serial API's not Electrical Engineering. The code is also a bit odd - it doesn't look original, but it doesn't look like a sound example either. You should perhaps start with something else. \$\endgroup\$ – Chris Stratton Sep 9 '17 at 18:09
  • 1
    \$\begingroup\$ @filo - not true. The code here already sets options.c_cc[VMIN]= 1 which is the very subject matter of your link. \$\endgroup\$ – Chris Stratton Sep 9 '17 at 20:50
  • 1
    \$\begingroup\$ @filo - No, as already pointed out hours ago that is incorrect. In actual fact the read function will return when VMIN (which has been set to one character) is received and the interval VTIME (which has been set to 1/10th of a second) has elapsed thereafter. \$\endgroup\$ – Chris Stratton Sep 10 '17 at 9:02
1
\$\begingroup\$

You are calling tcgetattr(fd,&options) to fill the options struct, the port may have been opened in canonical mode. Try clearing (or check the state of) this bit:

options.c_lflag &= ~ICANON;
\$\endgroup\$
  • \$\begingroup\$ I disabled canonical mode and it works. Thanks for your helping me to solve my problem which has been disturbing me for a couple of days. In the canonical mode, the RXD didn't receive LF(ASCII: 0x0A), so it paused only to wait for the "end of the line". Am I right? However, there is still one thing I do not understand. Why do the TXD keeps sending data when connected with the RXD of the same uart port? is it also because of the canonical mode? \$\endgroup\$ – james tom Sep 11 '17 at 13:55
  • \$\begingroup\$ UART TX and RX are totally separate. It makes no difference for the UART if the transmitter is connected to another device or to its own receiver. \$\endgroup\$ – filo Sep 11 '17 at 15:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.