S3C2440之UART操作(FIFO模式)
<1>
本文引用地址:http://2s4d.com/article/201611/318139.htm由于UART的波特率設(shè)置與時(shí)鐘有關(guān),此文設(shè)置FCLK:HCLK:PCLK=1 : 2 : 4,F(xiàn)CLK=200MHZ,遂先介紹時(shí)鐘的設(shè)置。
通常認(rèn)為上電復(fù)位后PLL是不穩(wěn)定的。因此在軟件重新配置PLLCON之前Fin代替MPLL直接供給Fclk。即便用戶不希望復(fù)位之后改變PLLCON的數(shù)值,用戶還是要用軟件寫入相同的數(shù)值到PLLCON寄存器中。
按照MDK4.22中啟動(dòng)代碼的設(shè)置來說明以下設(shè)置。
MPLL,UPLL根據(jù)公式即可算出,這里的MPS最后算出的Fclk=200Mhz。PCLK也就是50Mhz了。
注意到HDIVN這里設(shè)置為0x01,不為0,那么Fclk != Hclk,要將fast mode轉(zhuǎn)為異步模式,不然的話,F(xiàn)clk相當(dāng)于Pclk了。
由于MDK自帶的啟動(dòng)代碼沒有這部分代碼,所以自己加以修改了這部分。
FAST_TO_ASYN如果勾選的話,會(huì)選中
IFASYN_SETUP <> 0
MRCp15, 0, r1, c1, c0, 0
ORRr1, r1, #0xc0000000
MCRp15, 0, r1, c1, c0, 0
ENDIF
這樣就可以配置成自己想要設(shè)置的時(shí)鐘了。
關(guān)于串口的知識(shí)
3個(gè)獨(dú)立的串口,每一個(gè)都可以利用DMA和中斷方式操作。每個(gè)包含2個(gè)64字節(jié)FIFO,一個(gè)接,一個(gè)發(fā)。
非FIFO模式相當(dāng)于FIFO模式的一個(gè)寄存器緩沖模式。
每一個(gè)UART有7種狀態(tài),overrun錯(cuò)誤,校驗(yàn)錯(cuò)誤,幀錯(cuò)誤,斷點(diǎn),接收緩沖區(qū)準(zhǔn)備好,發(fā)送緩沖區(qū)為空,發(fā)送移位寄存器為空。錢4個(gè)被認(rèn)為是接收錯(cuò)誤狀態(tài),每一個(gè)都可以引起接收錯(cuò)誤狀態(tài)中斷請(qǐng)求,前提是UCONn中設(shè)置了receive-error-status-interrupt-request=1。
當(dāng)接收移位寄存器中的數(shù)據(jù)傳給FIFO的時(shí)候,且接收的數(shù)據(jù)觸發(fā)了Rx FIFO的閥值,Rx中斷產(chǎn)生了。
發(fā)送器中FIFO的還未發(fā)得數(shù)據(jù)到達(dá)Tx FIFO閥值的時(shí)候,Tx中斷產(chǎn)生了。
程序要點(diǎn):
本程序首先完成基本的UART0的配置,比如TXO RXO的管腳配置,這可以在啟動(dòng)文件里配置完成,接著ULCON0配置,UCON0配置,UFCON0配置,UMCON0配置,UBRDIV0配置,INTSUBMSK打開相應(yīng)位,INTMSK打開相應(yīng)位。
中斷程序里,接收和發(fā)都會(huì)引起UART0中斷,在里面要加以區(qū)分,是接還是發(fā)引起。接設(shè)置FIFO16字節(jié)觸發(fā),脈沖模式;發(fā)為0字節(jié)觸發(fā),電平模式。
注意到一上電,UART0配置完成后,就會(huì)觸發(fā)發(fā)中斷,因?yàn)榘l(fā)設(shè)置為0電平模式觸發(fā),所以為了避免無緣無故的觸發(fā),需要在某些時(shí)機(jī)下,禁止中斷。
功能:在串口上輸入16字節(jié),包括回車,然后會(huì)把輸入的字符回顯在串口終端上。
程序代碼:
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)測(cè)試可以完成功能。
評(píng)論