2011年6月15日 星期三

UART Baud Rate and FDR計算 2/2

上篇講到問題 UART接收錯誤的問題.

這篇會繼續討論 UART 相關 register 設定的部分.







/*LPC17xx */
uint32_t UARTInit( uint32_t PortNum, uint32_t baudrate )
{
  uint32_t Fdiv;
  uint32_t pclkdiv, pclk;

  if ( PortNum == 0 )
  {
    LPC_PINCON->PINSEL0 &= ~0x000000F0;
    LPC_PINCON->PINSEL0 |= 0x00000050;  /* RxD0 is P0.3 and TxD0 is P0.2 */
    /* By default, the PCLKSELx value is zero, thus, the PCLK for
    all the peripherals is 1/4 of the SystemFrequency. */
    /* Bit 6~7 is for UART0 */
    pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
    switch ( pclkdiv )
    {
      case 0x00:
      default:
        pclk = SystemFrequency/4;
        break;
      case 0x01:
        pclk = SystemFrequency;
        break;
      case 0x02:
        pclk = SystemFrequency/2;
        break;
      case 0x03:
        pclk = SystemFrequency/8;
        break;
    }

    LPC_UART0->LCR = 0x83;        /* 8 bits, no Parity, 1 Stop bit */
    Fdiv = ( pclk / 16 ) / baudrate ;    /*baud rate */
    LPC_UART0->DLM = Fdiv / 256;                           
    LPC_UART0->DLL = Fdiv % 256;
    LPC_UART0->LCR = 0x03;        /* DLAB = 0 */
    LPC_UART0->FCR = 0x07;        /* Enable and reset TX and RX FIFO. */

NVIC_EnableIRQ(UART0_IRQn);

    LPC_UART0->IER = IER_RBR | IER_THRE | IER_RLS;    /* Enable UART0 interrupt */
    return (TRUE);
  }
  else if ( PortNum == 1 )
  {
    LPC_PINCON->PINSEL4 &= ~0x0000000F;
    LPC_PINCON->PINSEL4 |= 0x0000000A;    /* Enable RxD1 P2.1, TxD1 P2.0 */
   
    /* By default, the PCLKSELx value is zero, thus, the PCLK for
    all the peripherals is 1/4 of the SystemFrequency. */
    /* Bit 8,9 are for UART1 */
    pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
    switch ( pclkdiv )
    {
      case 0x00:
      default:
        pclk = SystemFrequency/4;
        break;
      case 0x01:
        pclk = SystemFrequency;
        break;
      case 0x02:
        pclk = SystemFrequency/2;
        break;
      case 0x03:
        pclk = SystemFrequency/8;
        break;
    }

    LPC_UART1->LCR = 0x83;        /* 8 bits, no Parity, 1 Stop bit */
    Fdiv = ( pclk / 16 ) / baudrate ;    /*baud rate */
    LPC_UART1->DLM = Fdiv / 256;                           
    LPC_UART1->DLL = Fdiv % 256;
    LPC_UART1->LCR = 0x03;        /* DLAB = 0 */
    LPC_UART1->FCR = 0x07;        /* Enable and reset TX and RX FIFO. */

    NVIC_EnableIRQ(UART1_IRQn);
                  
    LPC_UART1->IER = IER_RBR | IER_THRE | IER_RLS;    /* Enable UART1 interrupt */
    return (TRUE);
  }
  return( FALSE );
}


使用ICE 設定中斷點在這程式中,讀取一些數值.
PortNum = 0 or 1,差異在於設定 UART 0 or UART 1相關暫存器.
baudrate 當然就是我們要設定的 baud rate值.


這篇我們著重在爲得到正確 Baud Rate 值,所計算該填寫的暫存器.


公式 1

順著程式看下來,
我得到
pclkdiv = 0
SystemFrequency = 72000000

因此
pclk ( 上式中的 PCLK ) = SystemFrequency/4 = 18000000


依照上圖流程:

(1)
BR : Baud Rate
DLest = PCLK/(16xBR)
= 18000000/(16x115200)
=9.7656

(2)
DLest 非整數,
 FRest =1.5
帶入下式.
(3)
 DLest = PCLK/(16xBRxFRest) 
 DLest = 6.5104

(4)
 FRest = PCLK/(16xBRxDLest) = 18000000/(16x115200x6) = 1.627


(5) 1.1< FRest < 1.9 ,True
(6)  查下表 FR = 1.625
DIVADDVAL = 5
MULVAL = 8

(7)
DLM = DLest [15:8] = 0
DLL =DLest [7:0] = 6



LPC_UART0->DLM = 0;
LPC_UART0->DLL = 6;
LPC_UART0->FDR = ((8<<4)|5); // DIVADDVAL, MULVAL


代入公式 1計算 Baud Rate值
18000000/(16x6x1.625)= 115384

(115384-115200)/115200 = 0.001597









0 留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...