免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2899 | 回复: 6
打印 上一主题 下一主题

串口问题求助,请兄弟们支援 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-30 17:49 |只看该作者 |倒序浏览
我的主机芯片是at91rm9200,现在发现了一个问题。
我的主机通过串口采集另外一个模块的数据,发现数据采集出错。时常有数据丢失。
后来修改了协议的代码。
协议开始读数据是通过一个buffer来读取的,就是read一个buffer,buffer大小为1024。有数据就返回。这样是会丢数据的。
后来把buffer改为1,也就是变为一个一个数据的读取,数据的正常了。

请问这是为啥?我总不能规定以后所有的采集协议读取都是一个一个字节读取吧。

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2010-08-31 08:56 |只看该作者
回复 1# klanet


    这个估计跟你的中断处理程序有关,你一个一个字节的读取,可能是串行阻塞型的,而开了软件buffer,有可能就是中断处理程序直接非阻塞的往里面塞数据,中断处理的优先级很高,一旦buffer满了就丢弃数据,具体还要仔细结合代码分析,方便的话可以贴一下代码。

论坛徽章:
0
3 [报告]
发表于 2010-08-31 09:56 |只看该作者
读写有没有加锁?

论坛徽章:
0
4 [报告]
发表于 2010-08-31 10:45 |只看该作者
本帖最后由 klanet 于 2010-08-31 10:56 编辑

回复 2# dreamice


    版主要的是那部分的代码?
驱动的还是协议层的?
协议层的
  1.     // 找头字符:
  2.     int i=0;
  3.     sRecStr[0] = 0;
  4.     do
  5.     {
  6.         ReadFile( hComm, (char*)sRecStr, 1, &lRead, NULL );
  7.         i++;
  8.     }while( lRead==1 && sRecStr[0]!=bySOI && i<nMaxDllBufNum-1 );

  9.     // 读后续数据串
  10.     if( lRead && sRecStr[0]==bySOI )
  11.     {
  12.         // 读取到数据段长度字符,以便决定本包总数据量.
  13.         ReadFile( hComm, (char*)sRecStr+1, 12, &lRead, NULL );
  14.         if( lRead==12 )
  15.         {
  16.             int nLen=0;
  17.             sscanf( (char *)sRecStr+9,"%04x", &nLen );
  18.             nLen = nLen & 0x0FFF;           // 去掉校验位
  19.             if( nLen+18 < nMaxDllBufNum-1 ) // 缓冲区溢出判断
  20.             {
  21.                 ReadFile( hComm, (char*)sRecStr+13, nLen+5, &lRead, NULL );
  22.             }
  23.             lRead += 12;
  24.         }
  25.         lRead++;
  26.     }

  27.     sRecStr[lRead] = 0;

  28.     // 跟踪调试的接收信息处理:回应信息记录。
复制代码
上面的是buffer读取,改为一个一个字节读取就不贴出来了,都差不多。

驱动代码在 drivers/serial/atmel_serial.c
下面是中断发的代码
  1. static void atmel_tx_chars(struct uart_port *port)
  2. {
  3.         struct circ_buf *xmit = &port->info->xmit;

  4.         if (port->x_char) {
  5.                 UART_PUT_CHAR(port, port->x_char);
  6.                 port->icount.tx++;
  7.                 port->x_char = 0;
  8.                 return;
  9.         }
  10.         if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  11.                 atmel_stop_tx(port);
  12.                 return;
  13.         }

  14.         while (UART_GET_CSR(port) & ATMEL_US_TXRDY) {
  15.                 UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  16.                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  17.                 port->icount.tx++;
  18.                 if (uart_circ_empty(xmit))
  19.                         break;
  20.         }

  21.         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  22.                 uart_write_wakeup(port);

  23.         if (uart_circ_empty(xmit))
  24.                 atmel_stop_tx(port);
  25. }
复制代码
下面是中断收
  1. static void atmel_rx_chars(struct uart_port *port)
  2. {
  3.         struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
  4.         struct tty_struct *tty = port->info->tty;
  5.         unsigned int status, ch, flg;

  6.         status = UART_GET_CSR(port);
  7.         while (status & ATMEL_US_RXRDY) {
  8.                 ch = UART_GET_CHAR(port);

  9.                 port->icount.rx++;

  10.                 flg = TTY_NORMAL;

  11.                 /*
  12.                  * note that the error handling code is
  13.                  * out of the main execution path
  14.                  */
  15.                 if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
  16.                                        | ATMEL_US_OVRE | ATMEL_US_RXBRK)
  17.                              || atmel_port->break_active)) {
  18.                         UART_PUT_CR(port, ATMEL_US_RSTSTA);        /* clear error */
  19.                         if (status & ATMEL_US_RXBRK
  20.                             && !atmel_port->break_active) {
  21.                                 status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);        /* ignore side-effect */
  22.                                 port->icount.brk++;
  23.                                 atmel_port->break_active = 1;
  24.                                 UART_PUT_IER(port, ATMEL_US_RXBRK);
  25.                                 if (uart_handle_break(port))
  26.                                         goto ignore_char;
  27.                         } else {
  28.                                 /*
  29.                                  * This is either the end-of-break
  30.                                  * condition or we've received at
  31.                                  * least one character without RXBRK
  32.                                  * being set. In both cases, the next
  33.                                  * RXBRK will indicate start-of-break.
  34.                                  */
  35.                                 UART_PUT_IDR(port, ATMEL_US_RXBRK);
  36.                                 status &= ~ATMEL_US_RXBRK;
  37.                                 atmel_port->break_active = 0;
  38.                         }
  39.                         if (status & ATMEL_US_PARE)
  40.                                 port->icount.parity++;
  41.                         if (status & ATMEL_US_FRAME)
  42.                                 port->icount.frame++;
  43.                         if (status & ATMEL_US_OVRE)
  44.                                 port->icount.overrun++;

  45.                         status &= port->read_status_mask;

  46.                         if (status & ATMEL_US_RXBRK)
  47.                                 flg = TTY_BREAK;
  48.                         else if (status & ATMEL_US_PARE)
  49.                                 flg = TTY_PARITY;
  50.                         else if (status & ATMEL_US_FRAME)
  51.                                 flg = TTY_FRAME;
  52.                 }

  53.                 if (uart_handle_sysrq_char(port, ch))
  54.                         goto ignore_char;

  55.                 uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);

  56.         ignore_char:
  57.                 status = UART_GET_CSR(port);
  58.         }

  59.         tty_flip_buffer_push(tty);
  60. }
复制代码

论坛徽章:
0
5 [报告]
发表于 2010-08-31 10:49 |只看该作者
回复 3# yikaikai


    没有

论坛徽章:
3
卯兔
日期:2013-08-26 22:14:57未羊
日期:2013-09-08 19:16:05未羊
日期:2014-10-23 10:34:12
6 [报告]
发表于 2010-08-31 10:51 |只看该作者
buffer的管理肯定有问题,把代码贴上来呗

论坛徽章:
0
7 [报告]
发表于 2010-08-31 11:02 |只看该作者
为一个陌生人无偿看这么长长的代码
这是一种怎样的神经病精神
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP