1. 程式人生 > >ARM裸機程式設計系列---UART

ARM裸機程式設計系列---UART

S5PV210 UART相關說明
通用非同步收發器簡稱UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它用來傳輸序列資料。傳送資料時,CPU將並行資料寫入UART,UART按照一定的格式在一根電線上序列發出;接收資料 時,UART檢測另一根電線的訊號,將序列收集在緩衝區中,CPU即可讀取UART獲得這些資料。
在S5PV210中,UART提供了4對獨立的非同步串列埠I/O埠,有4個獨立的通道,每個通道可以工作於DMA模式或者中斷模式。其中,通道0有 256byte的的傳送FIFO和256byte的接收FIFO,通道1有64byte的的傳送FIFO和64byte的接收FIFO,而通道2和3只有 16byte的的傳送FIFO和16byte的接收FIFO。
S5PV210的uart結構圖如下:
uart結構圖

UART使用標準的TTL/CMCOS邏輯電平來表示資料,為了增強資料抗干擾能力和提高傳輸長度,通常將TTL/CMOS邏輯電平轉換為RS-232邏輯電平,檢視原理圖可知Mini210S使用的是MAX3232SOP晶片,使用的是TX0和DX0:
GEC210UART原理圖
搜尋“XuTXD0”,可知:
晶片連線圖
通過設定UART相關暫存器,我們就可以驅動UART工作,達到傳送和接收字元的目的。
例子:

int main()
{
char c;
uart_init(); // 初始化串列埠
while (1)
{
c = getc (); // 接收一個字元c
putc(c+1); // 傳送字元c+1
}
return 0;
}

在main函式中,先會呼叫uart_init()初始化UART,然後使用getc接收PC發過來的字元,再呼叫putc()將該字元+1回覆給PC。

/*uart.c*/
void uart_init()
{
// 1 配置引腳用於RX/TX功能
GPA0CON = 0x22222222;
GPA1CON = 0x2222;
// 2 設定資料格式等
UFCON0 = 0x1; // 使能FIFO
UMCON0 = 0x0; // 無流控
ULCON0 = 0x3; // 資料位:8, 無校驗, 停止位: 1
UCON0 = 0x5; // 時鐘:PCLK,禁止中斷,使能UART傳送、接收 // 3 設定波特率
UBRDIV0 = UART_UBRDIV_VAL; // 35
UDIVSLOT0 = UART_UDIVSLOT_VAL; // 0x1
}

上述程式碼共有3個步驟,下面我們來一一講解每一個步驟:
第一步 配置引腳用於RX/TX功能
參考UART引腳連線圖,我們需要設定GPA0CON和GPA1CON暫存器使GPA0和GPA1引腳用於UART功能。
GPA0CON暫存器圖


GPA1CON暫存器圖

第二步 設定資料格式等
<1> ULCON0用來設定資料格式,見下圖
 ULCON0

Word Length = 11,8bit的資料;
Number of Stop Bit = 0,1bit的停止位;
Parity Mode = 000,無校驗;
Infrared Mode =0,使用普通模式;
所以ULCON0=0x3

<2> 9UCON0是UART的配置暫存器,見下圖
這裡寫圖片描述
這裡寫圖片描述

Receive Mode = 01 ,使用中斷模式或者輪詢模式;
Transmit Mode = 01,使用中斷模式或者輪詢模式;
Send Break Signal = 0,普通傳輸;
Loop-back Mode = 0,不使用迴環方式;
我們採用輪詢的方式接受和傳送資料,不使用中斷,所以bit[6-9]均為0;
Clock Selection = 0,使用PCLK作為UART的工作時鐘;
我們不使用DMA,所以bit[16]和bit[20]均為0;
所以UCON0 = 0x5

<3> UFCON0和UMCON0
這兩個暫存器比較簡單,UFCON0用來使能FIFO,UMCON0用來設定無流控。

第三步 設定波特率
波特率即每秒傳輸的資料位數,涉及兩個暫存器:UBRDIV0和UDIVSLOT0
這裡寫圖片描述
這裡寫圖片描述

波特率設定相關公式:UBRDIVn + (num of 1’s in UDIVSLOTn)/16 = (PCLK / (bps x 16)) ?1
其中,由Maximum Operating Frequency for Each Sub-block圖可知,UART工作於PSYS下,所以PCLK即PCLK_PSYS = 66.5MHz,我們的波特率bps設定為115200,所以
(66.5MHz/(115200 x 16)) – 1 = 35.08 = UBRDIVn + (num of 1’s in UDIVSLOTn)/16,所以我們設定UBRDIV0=35,UDIVSLOT0=0x1
getc()和putc()的程式碼如下:
// 接收一個字元
char getc(void)
{
while ((UFSTAT0 & 0xff) == 0); // 如果RX FIFO空,等待
return URXH0; // 取資料
}
// 傳送一個字元
void putc(char c)
{
while (UFSTAT0 & (1<<24)); // 如果TX FIFO滿,等待
UTXH0 = c; // 寫資料
}
UART資料傳送暫存器

UART資料接收暫存器
傳送/接收狀態暫存器

通 過讀UTRSTAT0 傳送/接收狀態暫存器,當Receive buffer data ready= 1時說明接收到資料,讀URXH0暫存器可以得到8bit的資料;當Transmitter empty = 1時說明可以傳送資料,寫8bit的資料到UTXH0。
完整程式碼地址:https://github.com/zhouhui321/gec210-nos/tree/master/uart_putchar