串口数据传输过快时,接收数据出现“卡顿”情况,有遇到过类似情况麻烦给下建议

逻辑运算符 2019-09-11 05:28:40
现象:
1.主机是嵌入式平台,当外部串口指令以10fps,每帧数据10个字节以内发送时,主机串口接收正常。
2.当指令发送速度提高时(大概有100fps),会出现接收卡顿的情况,即有几秒读到空白数据,然后一次性读到缓存区积累的数据。
3.该现象发生在波特率设置小于等于19200时出现,通讯波特率设置到115200后该现象消失。
4.用电脑串口工具接收外部串口是正常的,并未出现该现象。

在外部串口波特率(19200)无法改变的情况下,怎么配置串口参数去除该现象?
...全文
5209 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
m0_67361791 2022-02-25
  • 打赏
  • 举报
回复
楼主,这个问题你怎么解决的,我现在遇到相同的问题了,一个礼拜了,没有找到方法解决
hhhh63 2019-09-14
  • 打赏
  • 举报
回复
还有,设置优化编译参数也能加快
hhhh63 2019-09-14
  • 打赏
  • 举报
回复
接收程序耗时太多,优化代码,用DMA,加异常处理。
hjhj7591418 2019-09-12
  • 打赏
  • 举报
回复
使用串口的DMA接收,在主循环或者定时任务里进行串口接收DMA数据的处理。
逻辑运算符 2019-09-11
  • 打赏
  • 举报
回复
接收端基于Linux开发
配置接口代码如下
static int uart_setup( int fd, int baudrate, int flow_ctrl, int databits, int parity, int stopbits )
{
//串口主要设置结构体termios <termios.h>
struct termios options;
int baud_val;

/**1. tcgetattr函数用于获取与终端相关的参数。
*参数fd为终端的文件描述符,返回的结果保存在termios结构体中 */
tcgetattr( fd, &options );
/**2. 修改所获得的参数*/

//设置串口输入波特率和输出波特率
switch( baudrate )
{
case 115200:
baud_val = B115200;
break;
case 57600:
baud_val = B57600;
break;
case 38400:
baud_val = B38400;
break;
case 19200:
baud_val = B19200;
break;
case 9600:
baud_val = B9600;
break;
case 4800:
baud_val = B4800;
break;
case 2400:
baud_val = B2400;
break;
case 1200:
baud_val = B1200;
break;
case 300:
baud_val = B300;
break;
default :
printf("Unsupported baudrate\n");
return (-1);
}
cfsetispeed( &options, baud_val );
cfsetospeed( &options, baud_val );

options.c_cflag |= ( CLOCAL | 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;
default :
printf("Unsupported flow control\n");
return (-1);
}
//设置数据位
options.c_cflag &= ~CSIZE;//字符长度,屏蔽其他标志位,设置数据位之前一定要屏掉这个位
switch ( databits )
{
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 :
printf("Unsupported data size\n");
return (-1);
}

//设置校验位
switch ( parity )
{
case 'n':
case 'N': //无奇偶校验位。
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O'://设置为奇校验
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E'://设置为偶校验
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's':
case 'S': //设置为空格
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
printf("Unsupported parity\n");
return (-1);
}
// 设置停止位
switch ( stopbits )
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
printf("Unsupported stop bits\n");
return (-1);
}

options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
options.c_oflag = 0;
options.c_lflag = 0;
options.c_iflag &= ~(ICRNL | IXON);

//修改输出模式,原始数据输出
options.c_oflag &= ~OPOST;

/**3. 设置新属性,TCSANOW:所有改变立即生效*/
tcflush( fd, TCIFLUSH );//溢出数据可以接收,但不读
tcsetattr( fd, TCSANOW, &options );

return 0;
}

串口接收接口代码如下
static int uart_recv( int fd, char *data, int datalen )
{
int len = 0, ret = 0;
fd_set fs_read; /* 先声明一个 fd_set 集合来保存我们要检测的 fd句柄 */
struct timeval tv_timeout;

FD_ZERO( &fs_read ); /* 用select函数之前先把集合清零 */
FD_SET( fd, &fs_read ); /* 把要检测的句柄fd加入到集合里 */
tv_timeout.tv_sec = 0;//( 10*20/115200 + 2 ); /*设置等待最长时间*/
tv_timeout.tv_usec = 16000;

ret = select( fd+1, &fs_read, NULL, NULL, &tv_timeout ); /* 检测我们上面设置到集合fs_read里的句柄是否有可读信息 */
//printf("ret = %d\n", ret);

if( ret < 0 )
{
perror("select");/* 这说明select函数出错 */
return -1;
}
else
{ /* 说明等待时间还未到设定时间,fd的状态发生了变化 */
/* ret这个返回值记录了发生状态变化的句柄的数目,由于我们只监视了fd这一个句柄,所以这里一定ret=1,如果同时有多个句柄发生变化返回的就是句柄的总和了 */
/* 这里我们就应该从fd这个句柄里读取数据了,因为select函数已经告诉我们这个句柄里有数据可读 */
if ( FD_ISSET( fd, &fs_read ) ) /* 先判断一下socket这外被监视的句柄是否真的变成可读的了 */
{
len = read( fd, data, datalen ); /* 读取fd句柄里的数据 */
//printf("len = %d\n", len);
return len;
}
}
return 0;
}

27,511

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧