STM32的USART


幾個問題:

1、狀態寄存器(USART_SR)中的TC(Transmission complete)何時置位?它和TXE(Transmit data register empty,發送數據寄存器空)有何區別?可以先看看下面的圖:

根據上面的圖,TC置位的條件就是在上一個字節發完之后,數據寄存器仍為空(TXE=1)。USART_DR中的數據,只要移位寄存器把上一字節發完,馬上就可以移入移位寄存器,而USART_DR可以裝入新的數據。

2、波特率(Baud)的設置

從手冊知道,stm32的串口可以設置分數波特率,可以從APB時鍾得到精確的波特率。查看標准庫(v3.5)的設置波特率的部分函數,這種設置的方法精度足夠,以及發現一個在手冊里面(rev 14)沒有提到的位,先看代碼:

Init BRR
/* USART OverSampling-8 Mask */
#define CR1_OVER8_Set             ((u16)0x8000)  /* USART OVER8 mode Enable Mask */
#define CR1_OVER8_Reset           ((u16)0x7FFF)  /* USART OVER8 mode Disable Mask */

  uint32_t tmpreg = 0x00, apbclock = 0x00;
  uint32_t integerdivider = 0x00;
  uint32_t fractionaldivider = 0x00;
/*---------------------------- USART BRR Configuration -----------------------*/
  /* Configure the USART Baud Rate -------------------------------------------*/
  RCC_GetClocksFreq(&RCC_ClocksStatus);
  if (usartxbase == USART1_BASE)
  {
    apbclock = RCC_ClocksStatus.PCLK2_Frequency;
  }
  else
  {
    apbclock = RCC_ClocksStatus.PCLK1_Frequency;
  }
  
  /* Determine the integer part */
  if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
  {
    /* Integer part computing in case Oversampling mode is 8 Samples */
    integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));    
  }
  else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
  {
    /* Integer part computing in case Oversampling mode is 16 Samples */
    integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));    
  }
  tmpreg = (integerdivider / 100) << 4;

  /* Determine the fractional part */
  fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

  /* Implement the fractional part in the register */
  if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
  {
    tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
  }
  else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
  {
    tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
  }
  
  /* Write to USART BRR */
  USARTx->BRR = (uint16_t)tmpreg;

a、新的設置位:CR1_OVER8_Set,位於CR1的第15位,但是手冊里面沒有提到(rev14);根據手冊里面提到的波特率計算公式,估計默認這個位是0,代表每個bit采樣16次,而置位的時候,每bit采樣8次。手冊里的計算公式:

這個計算公式即按照每bit采樣16周期來計算的,所以上面的代碼在采樣8周期的時候,除以2了。

b、integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));  的計算與上面公式不一致,這是因為這行代碼下面還有這么一句:

tmpreg = (integerdivider / 100) << 4;

所以再除以100,合起來就相當於除以16了,為什么這樣子做?因為integerdivider是一個uint32,為了提高精度,所以那里乘以100了。

c、這個精度夠不夠?乘以100,相當於保留到小數點后兩位,而我們知道BRR的分數部分有4位,精度為1/16 = 0.0625,所以可以看到這個精度是夠的。那么上面可以不可以改成乘以250再除以1000呢?不行,因為加入apbclock用最高的頻率(72M),那么250*apbclock/4將溢出(uint32).

d、如果波特率特別高,而apbclock又較低,導致按照上面公式計算,結果USARTDIV小於1,則這樣是不行的,你不能指望USART還能自己提時鍾速度。這個時候,CR1_OVER8應該會有些作用,可以將在目前APB時鍾下的最大的波特率提升一倍。


免責聲明!

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



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