UART发送使用查询式发送,也就是调用库函数UARTCharPut(),源代码如下:<br />void CommSendData( INT8U ch, const INT8U *ptr, INT16U nBytes )<br />{<br /> INT32U base;<br /><br /> switch (ch)<br /> {<br /> case COMM1:<br /> base = COMM1_BASE;<br /> break;<br /><br /> case COMM2:<br /> base = COMM2_BASE;<br /> break;<br /><br /> default:<br /> return;<br /> }<br /><br /> while( nBytes-- )<br /> {<br /> UARTCharPut( base, *(ptr++) );<br /> }<br />}<br /><br />UART接收采用中断方式,系统开辟一个软件接收FIFO,用一个计数型信号量跟踪这个软件接收FIFO中的有效数据个数,其流程如下:<br />(1)产生串口接收中断<br />(2)读取接收到的字符<br />(3)如果软件接收FIFO没有满,将读取到的字符放入软件接收FIFO中<br />(4)OSSemPost(计数型信号量)<br /><br />在一个任务中,就可以按以下方式取出接收到的数据:<br />(1)OSSemPend(计数型信号量)<br />(2)如果步骤(1)成功,读取软件接收FIFO中的数据<br /><br />现在问题描述如下:<br />用LM3S8962的两个UART,波特率115200,使用“捷通串口调试软件V4.1”,将串口调试软件设置为“发送周期:10ms,连续不断的自动发送”,一次发送的数据量是100个字节,之所以在10ms的周期内发送100个字节,是因为115200的波特率的通讯量极限差不多是每秒10K/S,10ms发送100个字节,则1s就发送10K字节。<br /><br />打开两个“捷通串口调试软件”,每个调试软件对应到LM3S8962的一个UART,按上面的设置不断的连续发送数据,LM3S8962将接收到的数据在从相应的串口发送回来,这样发送一段时间以后,其中一个UART就会再也接收不到数据,而另一个串口还是可以正常收发。???????<br /><br />出现这种情况以后,仔细调试发现。那个接收不到数据的串口的软件FIFO计数值是满的(例如:软件FIFO的大小为100,则软件FIFO计数值就是100),而那个计数型信号量却为0,这样,当产生接收中断以后,发现软件FIFO是满的,则丢弃刚收到的数据,而在一个任务中要执行下面的操作才能接收到数据:<br />(1)OSSemPend(计数型信号量)<br />(2)如果步骤(1)成功,则从软件FIFO中取出数据<br />因为此时计数型信号量为0,所以任务无法从软件FIFO中取数,而任务不取数,则发送接收中断以后,接收中断有发现软件fifo是满的,有不会将数据放入软件fifo。正确的情况是计数型信号量的值应该和软件FIFO中的有效数据个数完全一致。<br />请问这是什么原因引起的??????<br /><br />代码如下:<br />/////////////// 产生接收中断以后,调用该函数将刚接收到的数据放入软件FIFO///////////////<br /><br />void CommPutRxChar (INT8U ch, INT8U c)<br />{<br />#if OS_CRITICAL_METHOD == 3<br /> OS_CPU_SR cpu_sr;<br />#endif<br /> OS_SEM_DATA sem;<br /> INT8U err;<br /> COMM_RING_BUF *pbuf;<br /><br /><br /> switch (ch) { /* Obtain pointer to communications channel */<br /> case COMM1:<br /> pbuf = &Comm1Buf;<br /> break;<br /><br /> case COMM2:<br /> pbuf = &Comm2Buf;<br /> break;<br /><br /> default:<br /> return;<br /> }<br /><br /> OS_ENTER_CRITICAL();<br /><br /> if (pbuf->RingBufRxCtr < COMM_RX_BUF_SIZE) { /* See if buffer is full */<br /> pbuf->RingBufRxCtr++; /* No, increment character count */<br /> *(pbuf->RingBufRxInPtr++) = c; /* Put character into buffer */<br /> if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE]) { /* Wrap IN pointer */<br /> pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];<br /> }<br /><br /> OS_EXIT_CRITICAL();<br /><br /> OSSemPost(pbuf->RingBufRxSem); /* Indicate that character was received */<br /><br /> return;<br /> }<br /> else<br /> {<br /> OS_EXIT_CRITICAL();<br /> }<br />}<br /><br /><br />/////////// 任务调用下面的函数从软件fifo中取数////////////////////<br /><br />INT8U CommGetChar (INT8U ch, INT16U to, INT8U *err)<br />{<br /> INT8U c;<br /> INT8U oserr;<br /> COMM_RING_BUF *pbuf;<br />#if OS_CRITICAL_METHOD == 3<br /> OS_CPU_SR cpu_sr;<br />#endif<br /> OS_SEM_DATA sem;<br /><br /><br /> switch (ch) { /* Obtain pointer to communications channel */<br /> case COMM1:<br /> pbuf = &Comm1Buf;<br /> break;<br /><br /> case COMM2:<br /> pbuf = &Comm2Buf;<br /> break;<br /><br /> default:<br /> *err = COMM_BAD_CH;<br /> return (NUL);<br /> }<br /> OSSemPend(pbuf->RingBufRxSem, to, &oserr); /* Wait for character to arrive */<br /><br /> if (oserr == OS_ERR_TIMEOUT) { /* See if characters received within timeout*/<br /> *err = COMM_RX_TIMEOUT; /* No, return error code */<br /> return (NUL);<br /> } else if(oserr == OS_ERR_NONE) {<br /> OS_ENTER_CRITICAL();<br /> pbuf->RingBufRxCtr--; /* Yes, decrement character count */<br /> /*<br /> OSSemQuery(pbuf->RingBufRxSem, &sem );<br /><br /> if( pbuf->RingBufRxCtr!=sem.OSCnt )<br /> FAIL();<br /> */<br /><br /> c = *(pbuf->RingBufRxOutPtr++); /* Get character from buffer */<br /> if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE]) { /* Wrap OUT pointer */<br /> pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];<br /> }<br /> OS_EXIT_CRITICAL();<br /> *err = COMM_NO_ERR;<br /> return (c);<br /> }<br /><br /> return (NUL);<br />} |
|