STM32之USART庫函數USART_SendData的bug


轉載自:http://www.cnblogs.com/itloverhpu/p/3250537.html

1.最近在調試ATM32F103CB時發現,一串數據的最后一個字節總是發送不出去,用的是RS485收發;

2.代碼如下:

    void uartReturn(unsigned char childBoardAddr)

 uchar temp = 0;  //must have
  
 temp += 0xAB;
  temp += childBoardAddr;
  temp += 0x30;
  temp += 0x01;
  temp += childBoardAddr;
 
 RS485_TX_EN;  //enable rs485 tx 
 
 sendByte(0xAB);
 sendByte(childBoardAddr);
 sendByte(0x30);
 sendByte(0x01);
 sendByte(childBoardAddr);
 sendByte(temp);
 
 RS485_RX_EN;  //enable rs485 rx 
}

其中:sendByte函數如下:

  void  sendByte( unsigned char data)
{
  //RS485_TX_EN; 
  USART_SendData( USART2,data );
  while( USART_GetFlagStatus( USART2,USART_FLAG_TXE ) == RESET ); //數據沒有被傳入輸出移位寄存器,則一直等待下去 
  //RS485_RX_EN;
}

同事幫忙改了一下lib庫函數:USART_SendData,在其后面加了: while((USARTx->SR&0x40)==0);//////////發現最后一字節數據會漏發,才加上的;

這調語句可不就是等價於:while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)嗎;

>>>>>>>>來看看網上是怎么說的?

用串口連續發送一串數字時,第一個數總是發不出去,我用STM32F103ZE,STM32F103CB都是這樣的情況,以下是代碼:
USART_SendData(USART1,0x06);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,0x07);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,0x08);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);

呵呵,第一字節發送不出去,看網友是怎么分析解答的吧:

1:這個問題的根本原因是復位后,TC和TXE標志位默認都是1,很多人喜歡這樣寫: 
    USART_SendData(USART1, (u8) ch);  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)  
    while在發送第一個字節時沒有起到應有作用,直接跳出,接着寫第二個字節,這時第一個字節還未發出,數據被破壞了.

看看datasheet,果然復位以后,SR=0x00c0;TC=TXE=1;

疑問:為什么網友說:只要第一個用TXE,其它用什么標志無所謂,都能正常發送。按道理,TXE也沒起到保護啊!!!

2.while的確很費時,另外當TDR寄存器中的數據被硬件轉移到移位寄存器的時候,TXE被硬件置位(注意:單緩沖器傳輸中使用該位);當包含有數據的一幀發送完成后,並且TXE=1時,由硬件將該位置’1’,只有在多緩存通訊中才推薦這種清除程序。其中TC判斷的是一幀數據,而TXE是當TDR數據傳到移位寄存器就被置位了,所以TC的時間比較長,很容易被下一次數據覆蓋~~~所以一般喜歡判斷TXE,數據寫到DR就可以了 ,剩下的工作就交給硬件了

3.一般的用TXE就可以了, TC一般用於需要延時的場合,比如說是232/485轉換器,需要得到TC后,才能將發送改變成接收,否則最后一個字節發送不完全。

 看來,3很符合我的情況:我的相當於2個等待:

        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET;   //@1

        while( USART_GetFlagStatus( USART2,USART_FLAG_TXE ) == RESET ); //@2

考慮一下:@2能不能拿掉呢??


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM