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