# UART in Linux: Keep sending for a long time while message is short [closed]

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 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);

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

else
{
}
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;

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
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: 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:

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.

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

• 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. – Spehro Pefhany Sep 9 '17 at 14:05
• @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. – Chris Stratton Sep 9 '17 at 18:02
• 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. – Chris Stratton Sep 9 '17 at 18:09
• @filo - not true. The code here already sets options.c_cc[VMIN]= 1 which is the very subject matter of your link. – Chris Stratton Sep 9 '17 at 20:50
• @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. – Chris Stratton Sep 10 '17 at 9:02

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;