Cortex-A9 UART
一、Exynos4412 UART 的特性
Exynos4412 中UART,有4 個獨立的通道,每個通道都可以工作於中斷模式或DMA 模式,即 UART 可以發出中斷或 DMA 請求以便在UART 、CPU 間傳輸數據。UART 由波特率發生器、發送器、接收器和控制邏輯組成。
使用系統時鐘時,Exynos4412 的 UART 波特率可以達到 4Mbps 。波特率可以通過編程進行 。
Exynos4412 UART 的通道 0有 256 字節的發送 FIFO 和 256 字節的接收FIFO ;通道 1、4有 64 字節的發送 FIFO 和 64 字節的接收FIFO;通道 2、3有 16 字節的發送FIFO 和 16 字節 的接收 FIFO 。發送數據時, CPU 先將數據寫入發送FIFO 中,然後 UART 會自動將FIFO 中的數據復制到“發送移位器” (Transmit Shifter )中,發送移位器將數據一位一位地發送到 TxDn 數據線上 (根據設定的格式,插入開始位 、較驗和停止)。接收數據時,“移位器” (Receive Shifter )將 RxDn 數據線上的數據一位一位的接收進來,然後復制到FIFO 中, CPU即可從中讀取數據。
Exynos4412 UART的每個通道支持停止位有 1位、 2位,數據位有 5、6、7或 8位,支持校驗功能,另外還有紅外發送 /接收功能。
Exynos4412 UART結構圖:
二、uart初始化步驟:
1、將所涉及的UART通道管腳設為UART功能
比如 UART 通道 0中, GPA0_0 、GPA0_1 分別用作 RXD0 、TXD0,要使用 UART 通道 0時,先設置 GPA0CON 寄存器將 GPA0_0 、GPA0_1 引腳的功能設為 RXD0 、TXD0 。
2、 選擇UART的時鐘源
Exynos4412 UART的時鐘源有八種選擇: XXTI 、XusbXTI 、SCLK_HDMI24M 、SCLK_USBPHY0 、 SCLK_HDMIPHY 、SCLKMPLL_USER_T 、SCLKEPLL 、SCLKVPLL ,由 CLK_SRC_PERIL0 寄存器控制。
選擇好時鐘源後,還可以通過 DIVUART0 ~4設置分頻系數 設置分頻系數 ,由 CLK_DIV_PERIL0 寄存器控制。 從分頻器得到的時鐘被稱為SCLK UART 。
SCLK UART 經過上圖中的“ UCLK Generator”後,得到UCLK ,它的頻率就是UART 的波特率。“ Generator UCLK Generator ”通過這 2個寄存器來設置: UBRDEVn 、UFRACVALn (在下面描述)。
3.、設置波特率:UBRDIVn寄存器(UART BAUD RATE DIVISOR)、UFRACVALn寄存器
根據給定的波特率、所選擇時鐘源頻率,可以通過以下公式計算 UBRDIVn 寄存器 (n 為 0~4,對應 5個 UART 通道 )的值。
UBRDIVn = (int)( UART clock / ( buad rate x 16) ) – 1
上式計算出來的 UBRDIVn 寄存器值不一定是整數, UBRDIVn 寄存器取其整數部分,小部分由 UFRACVALn 寄存器設置, UFRACVALn 寄存器的引入,使產生波特率更加精確。
例如,當UART clock為100MHz時,要求波特率為115200 bps,則:
100000000/(115200 x 16) – 1 = 54.25 – 1 = 53.25
UBRDIVn = 整數部分 = 53
UFRACVALn/16 = 小數部分 = 0.25
UFRACVALn = 4
4. 設置傳輸格式:ULCONn寄存器(UART LINE CONTROL)
ULCONn 寄存器 (n 為 0~4) 格式如下圖所示:
5. 設置UART工作模式:UCONn寄存器(UART CONTROL)
6. UFCONn寄存器(UART FIFO CONTROL)、UFSTATn寄存器(UART FIFO STATUS)
UFCON n寄存器用於設置是否使用FIFO,設置各 FIFO的觸發閥值,即發送 FIFO中有多少個數據時產生中斷、接收 FIFO 中有多少個數據時產生中斷。並可以通過設置UFCON n寄存器來復位各個 FIFO 。
讀取 UFSTAT n寄存器可以知道各個 FIFO 是否已經滿、其中有多少個數據。
不使用 FIFO 時,可以認為 FIFO 的深度為1,使用 FIFO 時 Exynos4412 的 FIFO 深度最高可達到256 。
7. UMCONn寄存器(UART MODEM CONTROL)、UMSTATn寄存器(UART MODEM STATUS)
這兩類寄存器用於流量控制,這裏不介紹。
8. UTRSTATn寄存器(UART TX/RX STATUS)
UTRSTAT n寄存器用來表明數據是否已經發送完畢、是否已經接收到數據,格式如下表所示,下面說的“緩沖區”,其實就是下圖中的 FIFO ,不使用 FIFO 功能時可以認為其深度為 1。
9. UERSTATn寄存器(UART ERROR STATUS)
用來表示各種錯誤是否發生,位 [0] 至位 [3] 為 1時分別表示溢出錯誤、校驗錯誤、幀錯誤、檢測到“ break ”信號。讀取這個寄存器時,它會自動清 0。
需要註意的是,接收數據時如果使用 FIFO ,則 UART 內部會使用一個“錯誤 FIFO ”來表明接收 FIFO 中哪個數據在接收過程發生了錯誤。 CPU 只有在讀出這個錯誤的數據時,才會覺察到發生了錯誤 。要想清除“FIFO ”,則必須讀出錯誤的數據,並讀出UERSTATn 寄存器。
10. UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)
CPU 將數據寫入這個寄存器, UART即會將它保存到緩沖區中,並自動發送出去。
11. URXHn寄存器(UART RECEIVE BUFFER REGISTER)
當 UART 接收到數據時,讀取這個寄存器,即可獲得數據。
三、示例程序編寫
![技術分享](/img/fz.gif)
#include "exynos_4412.h"
void delay_ms(unsigned int time);
void sendch(const char ch);
void sendstr(const char *str);
void recvch(char *ch);
void recvstr(char *str);
void myuart_init(void)
{
//設置引腳功能 UART RX TX
GPA1.CON = GPA1.CON & ~0xff | 0x22;
//設置傳輸格式 無校驗 停止位:1 數據位:8
UART2.ULCON2 = UART2.ULCON2 & ~0x7f | 0x3;
//設置接收、發送方式
UART2.UCON2 = UART2.UCON2 & ~0xf | 0x5;
//設置波特率 115200
UART2.UBRDIV2 = 53;
UART2.UFRACVAL2 = 4;
//DIV_VAL = (SCLK_UART / (bps * 16)) - 1
}
int main()
{
char buf[] = "uart send: hello world!\r\n";
char recvbuf[100];
myuart_init();
while(1)
{
sendstr(buf);
delay_ms(1000);
}
return 0;
}
void delay_ms(unsigned int time)
{
int i, j;
while(time--)
for(i = 0; i < 5; i++)
for(j = 0; j < 610; j++);
}
void sendch(const char ch)
{
/*等待發送器發送完成*/
while(!(UART2.UTRSTAT2 & 0x2));
UART2.UTXH2 = ch;
if (ch == ‘\n‘)
{
sendch(‘\r‘);
}
}
void sendstr(const char *str)
{
while(*str != ‘\0‘)
{
sendch(*str++);
}
}
void recvch(char *ch)
{
/*等待接收完成*/
while(!(UART2.UTRSTAT2 & 0x1));
*ch = UART2.URXH2;
}
void recvstr(char *str)
{
while(1)
{
recvch(str);
if(*str == ‘\r‘ )
{
*str = ‘\0‘;
break;
}
str++;
}
}
Cortex-A9 UART