JZ2440 UART裸機編程

ARM裸機1期加強版視頻課程配套WiKi第11課_串口(UART)的使用,
共2節(jié):第001節(jié)_輔線1_硬件知識_UART硬件介紹和第002節(jié)_S3C2440_UART編程,講的是JZ2440 UART裸機編程。
文字不能完全替代視頻,所以如果你看了這些文章感覺不錯卻不太懂,建議購買視頻進一步學習。
視頻購買地址:100ask.taobao.com,如下圖

第001節(jié)_輔線1_硬件知識_UART硬件介紹
1. 串口的硬件介紹
UART的全稱是Universal Asynchronous Receiver andTransmitter,即異步發(fā)送和接收。串口在嵌入式中用途非常廣泛:
· 打印調試信息
· 外接各種模塊:GPS、藍牙
串口因為結構簡單、穩(wěn)定可靠,廣受歡迎。通過三根線即可:發(fā)送、接收、地線。

通過TxD->RxD把ARM開發(fā)板要發(fā)送的信息發(fā)送給PC機。通過RxD->TxD線把PC機要發(fā)送的信息發(fā)送給ARM開發(fā)板。最下面的地線統(tǒng)一參考地。
2. 串口的參數
· 波特率:一般波特率都會有9600,19200,115200等選項。意思是每秒傳輸這么多個比特位數(bit)。
· 起始位:先發(fā)出一個邏輯”0”的信號,表示傳輸數據的開始。
· 數據位:可以是5~8位邏輯”0”或”1”。如ASCII碼(7位),擴展BCD碼(8位)。小端傳輸。
· 校驗位:數據位加上這一位后,使得“1”的位數應為偶數(偶校驗)或奇數(奇校驗),以此來校驗數據傳送的正確性。
· 停止位:它是一個字符數據的結束標志。
怎么發(fā)送一字節(jié)數據,比如‘A‘?
‘A’的ASCII值是0x41, 二進制就是01000001,怎樣把這8位數據發(fā)送給PC機呢?
1. 雙方約定好波特率(每一位占據的時間)
2. 規(guī)定傳輸協(xié)議
a. 原來是高電平,ARM拉低電平,保持1bit時間;
b. PC在低電平開始處計時;
c. ARM根據數據依次驅動TxD的電平,同時PC依次讀取RxD引腳電平,獲得數據;
前面圖中提及到了邏輯電平,也就是說代表信號1的引腳電平是人為規(guī)定的。如圖是TTL/CMOS邏輯電平下,傳輸‘A’時的波形:

在xV至5V之間,就認為是邏輯1,在0V至yV之間就為邏輯0。
如圖是RS-232邏輯電平下,傳輸‘A’時的波形:

在-12V至-3V之間,認為是邏輯1,在+3V至+12V之間為邏輯0。
RS-232的電平比TTL/CMOS高,能傳輸更遠的距離,在工業(yè)上用得比較多。
市面上大多數ARM芯片都不止一個串口,一般使用串口0來調試,使用其它串口外接模塊。
ARM芯片上的串口都是TTL電平,通過板子上或者外接的電平轉換芯片,轉成RS232接口,連接到電腦的RS232串口,實現(xiàn)兩者的數據傳輸:

現(xiàn)在的電腦越來越少有RS232串口接口,幾乎都有USB口。因此使用USB串口芯片將ARM芯片上的TTL電平轉換成USB串口電平,即可讓開發(fā)板通過USB與電腦數據傳輸。

上面的兩種方式,對ARM芯片的編程操作是一樣的。
ARM芯片是如何發(fā)送/接收數據?
如圖所示JZ2440 串口結構圖:

從上圖可知,要發(fā)送數據時,CPU控制內存要發(fā)送的數據通過FIFO傳給UART,UART里面的移位器依次將數據發(fā)送出去,在發(fā)送完成后產生中斷提醒CPU傳輸完成。
接收數據時,獲取接收引腳的電平,逐位放進接收移位器,再放入FIFO,寫入內存。在接收完成后產生中斷提醒CPU傳輸完成。
第002節(jié)_S3C2440_UART編程
在文件uart.c里需要編寫這幾個函數:
uart0_init() : 用于初始化串口
putchar() : 用于發(fā)送一個字符
getchar() : 用于接收一個字符
puts() : 用于發(fā)送一串字符
在uart0_init()的功能如下:
· 1. 設置引腳用于串口:根據原理圖和參考手冊設置GPH2,3用于TxD0, RxD0,并且為了將其保持為高電平,先設置其為上拉:
GPHCON & = ~((3<<4) | (3<<6));
GPHCON | = ((2<<4) | (2<<6));
GPHUP & = ~((1<<2) | (1<<3)); /* 使能內部上拉 */
· 2. 設置波特率
UCON0 = 0x00000005; //將uart時鐘設置為PCLK, 中斷/查詢模式:
uart clock=50M,波特率假設是115200,
根據公式
UBRDIVn = (int)( UARTclock / ( buad rate x 16) ) –1
得到
UBRDIVn = (int)(50000000 / ( 115200 x 16) ) –1 = 26
UBRDIV0 = 26;
· 3. 設置數據格式
數據格式設置為常用的8n1: 8個數據位, 無較驗位, 1個停止位
ULCON0 = 0x00000003; /* 8n1: 8個數據位, 無較驗位, 1個停止位 */
讀取UTRSTAT0寄存器,查詢其第2位判斷發(fā)送buff是否為空,即上一次發(fā)送是否完成,如果完成即向UTXH0寫入要發(fā)送的新數據;查詢其第0位判斷接收buff是否為空,即本次接收是否完成,如果接收完成,讀取URXH0的值。
int putchar(int c)
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = (unsigned char)c;
}
int getchar(void)
{
while (!(UTRSTAT0 & (1<<0)));
return URXH0;
}
循環(huán)輸出字符,就可以實現(xiàn)字符串的輸出:
int puts(constchar*s)
{
while (*s)
{
putchar(*s);
s++;
}
}
在main.c主函數里,先調用初始化函數uart0_init(),然后循環(huán)獲取用于輸入的數據,然后回顯出來。并且在收到`\r`回車時,輸出`\n`換行,有些時候`\n`表示回車,則輸出`\r`換行。
main.c代碼如下:
#include "s3c2440_soc.h"
#include "uart.h"
int main(void)
{
unsigned char c;
uart0_init();
puts("Hello, world!\n\r");
while(1)
{
c = getchar();
if (c =='\r')
{
putchar('\n');
}
if (c =='\n')
{
putchar('\r');
}
putchar(c);
}
return0;
}
// PS: 由于篇幅限制,這里未給出全部代碼,要做實驗的話請去百度網盤下載相關代碼:https://eyun.baidu.com/s/3b1UtLc
預知更多干貨,請關注微信公眾號baiwenkeji。