S3C2440之UART操作(FIFO模式)
<1>
本文引用地址:http://2s4d.com/article/201611/318139.htm由于UART的波特率設置與時鐘有關,此文設置FCLK:HCLK:PCLK=1 : 2 : 4,F(xiàn)CLK=200MHZ,遂先介紹時鐘的設置。
通常認為上電復位后PLL是不穩(wěn)定的。因此在軟件重新配置PLLCON之前Fin代替MPLL直接供給Fclk。即便用戶不希望復位之后改變PLLCON的數(shù)值,用戶還是要用軟件寫入相同的數(shù)值到PLLCON寄存器中。
按照MDK4.22中啟動代碼的設置來說明以下設置。
MPLL,UPLL根據(jù)公式即可算出,這里的MPS最后算出的Fclk=200Mhz。PCLK也就是50Mhz了。
注意到HDIVN這里設置為0x01,不為0,那么Fclk != Hclk,要將fast mode轉為異步模式,不然的話,F(xiàn)clk相當于Pclk了。
由于MDK自帶的啟動代碼沒有這部分代碼,所以自己加以修改了這部分。
FAST_TO_ASYN如果勾選的話,會選中
IFASYN_SETUP <> 0
MRCp15, 0, r1, c1, c0, 0
ORRr1, r1, #0xc0000000
MCRp15, 0, r1, c1, c0, 0
ENDIF
這樣就可以配置成自己想要設置的時鐘了。
關于串口的知識
3個獨立的串口,每一個都可以利用DMA和中斷方式操作。每個包含2個64字節(jié)FIFO,一個接,一個發(fā)。
非FIFO模式相當于FIFO模式的一個寄存器緩沖模式。
每一個UART有7種狀態(tài),overrun錯誤,校驗錯誤,幀錯誤,斷點,接收緩沖區(qū)準備好,發(fā)送緩沖區(qū)為空,發(fā)送移位寄存器為空。錢4個被認為是接收錯誤狀態(tài),每一個都可以引起接收錯誤狀態(tài)中斷請求,前提是UCONn中設置了receive-error-status-interrupt-request=1。
當接收移位寄存器中的數(shù)據(jù)傳給FIFO的時候,且接收的數(shù)據(jù)觸發(fā)了Rx FIFO的閥值,Rx中斷產(chǎn)生了。
發(fā)送器中FIFO的還未發(fā)得數(shù)據(jù)到達Tx FIFO閥值的時候,Tx中斷產(chǎn)生了。
程序要點:
本程序首先完成基本的UART0的配置,比如TXO RXO的管腳配置,這可以在啟動文件里配置完成,接著ULCON0配置,UCON0配置,UFCON0配置,UMCON0配置,UBRDIV0配置,INTSUBMSK打開相應位,INTMSK打開相應位。
中斷程序里,接收和發(fā)都會引起UART0中斷,在里面要加以區(qū)分,是接還是發(fā)引起。接設置FIFO16字節(jié)觸發(fā),脈沖模式;發(fā)為0字節(jié)觸發(fā),電平模式。
注意到一上電,UART0配置完成后,就會觸發(fā)發(fā)中斷,因為發(fā)設置為0電平模式觸發(fā),所以為了避免無緣無故的觸發(fā),需要在某些時機下,禁止中斷。
功能:在串口上輸入16字節(jié),包括回車,然后會把輸入的字符回顯在串口終端上。
程序代碼:
uart.c
/** PC<----->2440UART0*/#include "S3C2440.h"#include "uart.h"static u8 string[512] = {0,0};static u8 data_is_ready = 0;void init_uart0(void){rULCON0 = 0x03; rUCON0 = (0x05) | (1<<9);//15---12 11-10 9 8 7 6 5 4 3-2 1-0//not pclk/n pclk Tlevel Rpulse timeout disable rx error int disable loop dis break dis int or poll int or pollrUFCON0 = (0x0<<6) | (0x02<<4) | (0x01<<0);//0 0 1 1 0 0 0 1//Tx trigger level = 0 Rx trigger level = 16bytes FIFO enable=1rUMCON0 = 0x0;rUBRDIV0 = UART_BRDIV;rINTSUBMSK &= ~BIT_SUB_RXD0;rINTMSK &= ~BIT_UART0;pHandleUART0 = UART0_Handle;}void __irq UART0_Handle(void){u8* ps = string;if(rSUBSRCPND&0x01){rINTSUBMSK |= BIT_SUB_RXD0;while(((rUFSTAT0&0x1f)>0))*ps++ = RdURXH0_L;data_is_ready = 1; rSUBSRCPND = BIT_SUB_RXD0;}else if(rSUBSRCPND&0x02){int i;rINTSUBMSK |= BIT_SUB_TXD0; while((!(rUFSTAT0&(1<<14))) && (*ps != r)){WrUTXH0_L(*ps++); for(i=0; i<100;i++);} data_is_ready = 0;rSUBSRCPND = BIT_SUB_TXD0; }rSRCPND = BIT_UART0;rINTPND = BIT_UART0;if(data_is_ready)rINTSUBMSK &= ~(BIT_SUB_TXD0); elserINTSUBMSK &= ~(BIT_SUB_RXD0); }
main.c
#include "S3C2440.h"#include "uart.h"int main(void){ rGPBDAT |= (0xf<<5);init_uart0();while(1);}
經(jīng)測試可以完成功能。
評論