這問題是在使用 LPC17xx MCB1700 Sample Code Bundle for LPC17xx Peripherals using Keil's MDK-ARM V2.00 (Jan 10, 2011) Project UART 時遇到的問題.
程式中將UART0/1 設定 Baud Rate 57600 (bps) , 8bit , 1 stop bit,no parity , no flow ctrl ,這個範例實驗是接上rs232後,pc端開啟 HT. 或是 pUTTY,在 pUTTY中敲鍵盤按鍵,該按鍵 ACSII 碼會透過 PC RS232 TX 傳送至 LPC17xx UART Rx , 再由 LPC17xx Tx將同樣的字元傳送至PC端,顯示在 putty上. 相同的實驗在,LPCXpresso for LPC1114 code 中也有.
問題是將 UART 0/1的 Baud Rate改為 115200的時候,顯示就不正常.
而57600的時後就沒問題.
這是怎麼一回事?
基本的排除方法,我列出:
1,2 點在我的環境下都沒問題,一直都在使用. ( 不過工作經驗告訴我,偶爾還是會遇到該去拜拜的時候,明明前一天還都正常,隔天來就出問題 ), 不過因為開頭敘述的, baud rate 設定 57600的時候實驗是正常的.所以更可增強1,2項 OK這點.
3. 使用ICE Debug,設定中斷點監看接收資料
在下列程式中,紅色字體部分設下中斷點.
所以在UART0/1 接收到字元之後,中斷. 查看是否進入中斷,若有接著檢查接收資料.
實驗後中斷發生,
檢查接收資料並非0x55. (大寫 U的ASCII code)
於是進行4,實際量測訊號.
輪到3,4. 理論上....... 順序應該是4先做. XD (不早說 )
寫到這裡才想到,但是懶的掉換順序嘛....
分別量測得到 57600 (第一張圖),與 115200 下圖
訊號都沒有問題. 算出來的1 bit寬度也都在範圍內(後面會介紹如何計算).
所以推測硬體訊號正常,但是程式中斷看到的卻不是正確的值.
因此覺得訊號進IC後到軟體中斷這中間出現問題.
因為 UART (Universal Asynchronous Receiver/Transmitter) 非同步傳送接收訊號. 也就是沒有同步的Clock訊號( 像是I2C, SPI 都有CLOCK訊號). 所以兩端要能解讀正確訊號,必須先兩端要有默契. 要有哪些默契?
從這張圖就可看出, Speed ( Baud Rate ), Data bits, Stop bits, Parity, Flow Control
這些設定就是所謂雙方需要的默契.
其中的解釋可以參考 WIKI : UART 或是 搜尋 UART能見到很多資料.
而通常遇過的問題之中,就屬 Baud Rate 出錯的問題較多.
查看 Line Control Register ( LCR ) 設定
以及程式中 MCR ( Modem Control Register ) 都未設定( default為 disable) ,就等同 Flow Control 無.
到此為止,可以差不多推論出問題就是 Baud Rate設定上出了問題. WIKI :Baud
換言之,Baud Rate在這邊就是每秒(傳送/接收)的bit數量.
因此 Baud Rate 115200 也就是 115200 bit/per sec ,
換算回來 1個bit 的時間是 1/115200 = 8.68555x10(-6) [sec] = 8.68555 usec
圖2 一個 pulse的寬度 8.4 us ( cursor 不是對很準稍有誤差 )
在LPC1114系列中Baud Rate相關 register 如何計算填寫?
就在這個 UARTInit function中,
下篇繼續講解.. UART Baud Rate and FDR計算 2/2
附錄: ASCII Table
UARTInit(0, 57600); /* baud rate setting */
UARTInit(1, 57600); /* baud rate setting */
程式中將UART0/1 設定 Baud Rate 57600 (bps) , 8bit , 1 stop bit,no parity , no flow ctrl ,這個範例實驗是接上rs232後,pc端開啟 HT. 或是 pUTTY,在 pUTTY中敲鍵盤按鍵,該按鍵 ACSII 碼會透過 PC RS232 TX 傳送至 LPC17xx UART Rx , 再由 LPC17xx Tx將同樣的字元傳送至PC端,顯示在 putty上. 相同的實驗在,LPCXpresso for LPC1114 code 中也有.
1. baud rate 57600 |
問題是將 UART 0/1的 Baud Rate改為 115200的時候,顯示就不正常.
而57600的時後就沒問題.
這是怎麼一回事?
基本的排除方法,我列出:
- Cable有無問題?(這類Cable常遇到 TX/RX有交換過)
- TX/RX 有沒接反?( PC TX to MCU RX , MCU TX to PC RX 當然這中間有 Level shift or USB to RS232 or to UART IC)
- 使用ICE Debug,設定中斷點監看接收資料
- 實際使用示波器量測訊號
1,2 點在我的環境下都沒問題,一直都在使用. ( 不過工作經驗告訴我,偶爾還是會遇到該去拜拜的時候,明明前一天還都正常,隔天來就出問題 ), 不過因為開頭敘述的, baud rate 設定 57600的時候實驗是正常的.所以更可增強1,2項 OK這點.
3. 使用ICE Debug,設定中斷點監看接收資料
在下列程式中,紅色字體部分設下中斷點.
所以在UART0/1 接收到字元之後,中斷. 查看是否進入中斷,若有接著檢查接收資料.
while (1)
{ /* Loop forever */
if ( UART0Count != 0 )
{
LPC_UART0->IER = IER_THRE | IER_RLS; /* Disable RBR */
UARTSend( 0, (uint8_t *)UART0Buffer, UART0Count );
UART0Count = 0;
LPC_UART0->IER = IER_THRE | IER_RLS | IER_RBR; /* Re-enable RBR */
}
if ( UART1Count != 0 )
{
LPC_UART1->IER = IER_THRE | IER_RLS; /* Disable RBR */
UARTSend( 1, (uint8_t *)UART1Buffer, UART1Count );
UART1Count = 0;
LPC_UART1->IER = IER_THRE | IER_RLS | IER_RBR; /* Re-enable RBR */
}
}
實驗後中斷發生,
檢查接收資料並非0x55. (大寫 U的ASCII code)
於是進行4,實際量測訊號.
輪到3,4. 理論上....... 順序應該是4先做. XD (不早說 )
寫到這裡才想到,但是懶的掉換順序嘛....
分別量測得到 57600 (第一張圖),與 115200 下圖
2. baud rate 115200 |
訊號都沒有問題. 算出來的1 bit寬度也都在範圍內(後面會介紹如何計算).
所以推測硬體訊號正常,但是程式中斷看到的卻不是正確的值.
因此覺得訊號進IC後到軟體中斷這中間出現問題.
因為 UART (Universal Asynchronous Receiver/Transmitter) 非同步傳送接收訊號. 也就是沒有同步的Clock訊號( 像是I2C, SPI 都有CLOCK訊號). 所以兩端要能解讀正確訊號,必須先兩端要有默契. 要有哪些默契?
這些設定就是所謂雙方需要的默契.
其中的解釋可以參考 WIKI : UART 或是 搜尋 UART能見到很多資料.
而通常遇過的問題之中,就屬 Baud Rate 出錯的問題較多.
查看 Line Control Register ( LCR ) 設定
LPC_UART1->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
以及程式中 MCR ( Modem Control Register ) 都未設定( default為 disable) ,就等同 Flow Control 無.
到此為止,可以差不多推論出問題就是 Baud Rate設定上出了問題. WIKI :Baud
換言之,Baud Rate在這邊就是每秒(傳送/接收)的bit數量.
因此 Baud Rate 115200 也就是 115200 bit/per sec ,
換算回來 1個bit 的時間是 1/115200 = 8.68555x10(-6) [sec] = 8.68555 usec
圖2 一個 pulse的寬度 8.4 us ( cursor 不是對很準稍有誤差 )
在LPC1114系列中Baud Rate相關 register 如何計算填寫?
就在這個 UARTInit function中,
/*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. */
LPC_UART0->FDR = ((10<<4)|1);
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. */
LPC_UART1->FDR = ((10<<4)|1);
NVIC_EnableIRQ(UART1_IRQn);
LPC_UART1->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART1 interrupt */
return (TRUE);
}
return( FALSE );
}
下篇繼續講解.. UART Baud Rate and FDR計算 2/2
附錄: ASCII Table
想請教一下,我是使用LPC1114F,想請問如何使用UART TX發送訊號,然後拉出接腳在示波器上看到,我是初學著~這方面不是很會,謝謝~~
回覆刪除不好意思,我是使用LPC1114F,想請問要如何像你一樣把訊號拉出來,在示波器上看,我的範例程式都是發射字串用終端機顯示的,想請問如何用市波器看~~謝謝
回覆刪除Hi 葉老二,
回覆刪除針對你的問題,簡單的說就是將 TX 訊號接到示波器上,地接好就可以看訊號。
謝謝您的協助,已經可以在示波器看到訊號了,也成功地將UART訊號加到LED燈上了,另外想請問大大會用SPI介面嗎?因為我看書上都有,他的速度比UART快很多,我想將SPI產生的訊號拉出來加到LED燈上面,不知行不行得通??
刪除作者已經移除這則留言。
刪除作者已經移除這則留言。
刪除接上LED? 速度很快的時候肉眼其實也看不出什麼。不過你還是可以試看看。
回覆刪除另外我也有些 SPI相關文章
http://mcudiy.blogspot.tw/search/label/SPI
忘記跟大大說,因為要做光通訊,要用可見光LED傳資料,UART太慢了,最快只能到115200k所以才想說要用SPI,只是現在卡在訊號不知怎麼讓他從LPC1114送出來~~
回覆刪除http://mcudiy.blogspot.tw/search/label/SPI 給你參考看看。 輸出就看 MOSI pin.
刪除