1. 程式人生 > >JZ2440 裸機驅動 第11章 通用異步收發器UART

JZ2440 裸機驅動 第11章 通用異步收發器UART

secure 初始 輸入 receive ready mode lin 個數 0x03

本章目標:

了解UART原理; 掌握S3C2410/S3C2440中UART的使用

11.1 UART原理及UART內部使用方法

11.1.1 UART原理說明

UART用於傳輸串行數據: 發送數據時,CPU將並行數據寫入UART,UART按照一定的格式在一根電線上串行發出; 接收數據時,UART檢測另一根電線上的信號,將串行收集放在緩沖區中,CPU即可讀取 UART獲得這些數據。 UART之間以全雙工方式傳輸數據,最精簡的連接方式只有3根線:TxD、RxD、Gnd。 UART使用標準的TTL/CMOS邏輯電平(0~5V、0~3.3V、0~2.5V或0~1.8V)來表示數據, 高電平表示1,低電平表示0.為了增強數據抗幹擾能力、提高傳輸長度,通常將TTL/CMOS 邏輯電平轉換為RS-232邏輯電平,3~12V表示0,-3~-12V表示1。

11.1.2 S3C2410/S3C2440 UART的特性

S3C2410/S3C2440中UART功能類似,有3個獨立的通道,每個通道都可以工作於中斷 或DMA模式。即UART可以發出中斷或DMA請求以便在UART、CPU間傳輸數據。 UART由波特率發生器、發送器、接收器和控制邏輯組成。 使用系統時鐘時,S3C2410的UART波特率可以達到230.4Kbit/s,S3C2440則可以達到 115.2Kbit/s;如果使用UEXTCLK引腳提供的外部時鐘,則可以達到更高的波特率。波特率 可以通過編程進行控制。 S3C2410 UART的每個通道都有16字節的發送FIFO和16字節的接收FIFO,S3C2440 UART 的FIFO深度為64。 S3C2410/S3C2440 UART的每個通道支持的停止位有1、2位,數據位有5、6、7或8位, 支持校驗功能,另外還有紅外發送/接收功能。

11.1.3 S3C2410/S3C2440 UART的使用

在使用UART之前需要設置波特率、傳輸格式(多少數據位、是否使用校驗位、是奇校驗 還是偶校驗、有多少停止位、是否使用流量控制);對於S3C2410/S3C2440,還要選擇所涉及 管腳為UART功能、選擇UART通道的工作模式為中斷模式或DMA模式。設置好之後,向某個寄存器 中寫入數據即可發送,讀取某個寄存器即可得到接收到的數據。可以通過查詢狀態寄存器或 設置中斷來獲知數據是否已經發送完畢、是否已經接收到數據。 針對上述過程,下面一一說明。 1.將所涉及的UART通道管腳設為UART功能 2.UBRDIVn寄存器(UART BAUD RATE DIVISOR):設置波特率 S3C2410 UART 的時鐘源有兩種選擇:PCLK、UEXTCLK;S3C2440 UART的時鐘源有 三種選擇:PCLK、UEXTCLK、FCLK/n,其中n的值通過UCON0~UCON2聯合設置。 根據給定的波特率、所選擇的時鐘源的頻率,可以通過如下公式計算UBRDIVn寄 存器(n為0~2,對應3個UART通道)的值。 UBRDIVn = (int)(UART clock / (buad rate * 16)) - 1 上面計算出來的UBRDIVn寄存器不一定是整數,只要其誤差在1.87%之內即可。誤
差計算公式如下: tUPCLK = (UBRDIVn + 1) * 16 * 1Frame/(UART clock) //實際的UART時鐘 tUEXACT = 1Frame / baud-rate //理論的UART時鐘 UART error = (tUPCLK - tUEXACT) / tUEXACT * 100% //誤差 3.ULCONn寄存器(n:0~2)(UART LINE CONTROL):設置傳輸格式 技術分享 4.UCONn寄存器(UART CONTROL) UCONn寄存器用於選擇UART時鐘源、設置UART中斷方式等。由於S3C2410的UART 只有兩個時鐘源,S3C2440有3個時鐘源,所以在選擇和設置時鐘源時有所不同。 S3C2410的UCONn寄存器格式如下表11.2所示。 技術分享 S3C2440的UCONn寄存器在UART時鐘的選擇方面與S3C2410有所不同,從位[10]往上 的位含義不一樣,並且原來的位[4]用於徐娜則是否發出“break”信號,這些位的含義 如表11.3所示。 技術分享 UCON0、UCON1、UCON2這三個寄存器的位[15:12]一起用來確定n的值,它們的意義如下。 (1)UCON2[15]:“FCLK/n”使能位。 它等於0時,禁止使用“FCLK/n”作為UART時鐘源;等於1時,可以用作UART時鐘源。 (2)n的值設置。 UCON0[15:12]、UCON1[15:12]、UCON2[14:12]三者用於設置n的值,當其中一個被射程非 0時,其他兩個必須為0. ① n的值處於7~21處時,UART時鐘 = FCLK/(divider + 6),divider 為UCON0[15:12]的值,大於0。 ② n的值處於22~36時,UART時鐘 = FCLK/(divider + 21),divider為UCON1[15:12]的值,大於0。 ③ n的值處於37~43時,UART時鐘 = FCLK/(divider + 36),divider為UCON2[14:12]的值,大於0. ④ UCON0[15:12]、UCON1[15:12]、UCON2[14:12]都等於0時,UART時鐘:FCLK/44。 5.UFCONn寄存器(UART FIFO CONTROL)、UFSTATn寄存器(UART FIFO STATUS) UFCONn寄存器用於設置是否使用FIFO,設置個FIFO的觸發值。並可以通過設置UFCONn 寄存器來復位個寄存器。 讀取UFSTATn寄存器可以知道各個FIFO是否已經滿、其中有多少個數據。 不使用FIFO時,可以認為FIFO的深度為1,使用FIFO時,S3C2410的FIFO深度為16, S3C2440的FIFO深度為64.這兩類寄存器各位的含義請參考數據手冊,後面的實例部分沒有 使用FIFO。 6.UMCONn寄存器(UART MODEM CONTROL)、UMSTATn寄存器(UART MODEM STATUS) 這兩類寄存器用於流控,這裏不介紹。 7.UTRSTATn寄存器(UART TX/RX STATUS) UTRSTATn寄存器用於表明數據是否已經發送完畢、是否已經接收到數據,格式如表11.4 所示。緩沖區起始就是圖11.3中的FIFO,只不過不使用FIFO功能時可以認為其深度為1。 技術分享 8.UERSTATn寄存器(UART ERROR STATUS) 用於表示各種錯誤是否發生,位[0]~位[3]為1時分別表示溢出錯誤、校驗錯誤、幀錯誤、 檢測到“break”信號。讀取這個寄存器時,它會自動清零。 註意:接收數據時,如果使用FIFO,則UART內部會使用一個“錯誤FIFO”來表明接收FIFO 中哪個數據在接收過程中發生了錯誤。CPU只有在讀出這個錯誤的數據時,才會察覺到發生了錯 誤。要想清除“錯誤FIFO”,則必須讀出錯誤的數據,並讀出UERSTATn寄存器。 9.UTXHn寄存器(UART TRANSMIT BUFFER REGISTER) CPU將數據寫入這個寄存器,UART即將它保存到緩沖區中,並自動發送出去。 10.URXHn寄存器(UART RECEIVE BUFFER REGISTER) 當UART接收到數據時,CPU讀取這個寄存器,即可獲得數據。

11.2 UART 操作實例

11.2.1 代碼詳解

本實例代碼在/work/hardware/uart目錄下。目的是在串口上輸入一個字符,單板收到後將 它的ASCII值加1後,從串口輸出。 首先設置MPLL提高系統時鐘,令PCLK為50MHz,UART將選擇PCLK作為時鐘源。將代碼復制到 SDRAM之後,調用main函數。這些代碼與第10章相似。重點在於main函數對UART0的初始化、收發 數據,這由3個函數實現:usat0_init、getc和putc,它們在serial.c文件中。 1.UART初始化 uart0_init函數代碼如下: 技術分享
 1 #define PCLK              50000000    //init.c中的clock_init函數設置PCLK為50MHz
 2 #define UART_CLK          PCLK        //UART0的時鐘源設為PCLK
 3 #define UART_BAUD_RATE    115200      
 4 #define UART_BRD          ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)
 5 
 6 /*
 7 *初始化UART0
 8 *115200, 8N1, 無流控
 9 */
10 void uart0_init(void)
11 {
12     GPHCON |= 0xa0;    //GPH2、GPH3用作TXD0、RXD0
13     GPHUP   = 0x0c;    //GPH2、GPH3內部上拉
14     
15     ULCON0 = 0x03;    //波特率:115200,8N1
16     UCON0  = 0x05;    //查詢方式,UART時鐘源為PCLK
17     UFCON0 = 0x00;    //不使用FIFO
18     UMCON0 = 0x00;    //不使用流控
19     UBRDIV0 = UART_BRD;    //波特率:115200
20 }
serial.c->uart0_init() 2.發送字符的函數 本實例不使用FIFO,發送字符前,先判斷上一個字符是否已經發送出去。如果沒有, 則不斷查詢UTRSTAT0寄存器的位[2],當它為1時表示已經發送完畢。於是,即可向UTXH0寄 存器中寫入要發送的字符。代碼如下(宏TXD0READY被定義為“(1 << 2)”): 技術分享
 1 /*
 2 *發送一個字符
 3 */
 4 void putc(unaigned char c)
 5 {
 6     /*等待,直到發送緩沖區中的數據已經全部發送出去*/
 7     while(!(UTRSTAT0 & TXD0READY));
 8     
 9     /*向UTXH0寄存器中寫數據,UART自動將其發送出去*/
10     UTXH0 = c;
11 }
serial.c->putc() 3.接收字符的函數 試圖讀取數據前,先查詢UTRSTAT0寄存器的位[1],當它為1時,表示接收緩沖區中有數據。 於是,即可讀取URXH0得到數據。代碼如下(宏RXD0READY被定義為“(1)”): 技術分享
 1 /*
 2 *接收字符
 3 */
 4 unsigned char getc(void)
 5 {
 6     /*等待,知道接收緩沖區中有數據*/
 7     while(!(UTRSTAT0 & RXD0READY));
 8     
 9     /*直接讀取URXH0寄存器,即可獲得接收到的數據*/
10     return URXH0;
11 }
serial.c->getc() 4.主函數 初始化完UART0之後,不斷地讀取串口數據,並判斷它是否是數據或字符。如果是的話, 將它加1後從串口輸出。代碼如下: 技術分享
 1 #include "serial.h"
 2 
 3 int main()
 4 {
 5     unsigned char c;
 6     uart0_init();    //波特率:115200,8N1
 7     
 8     while(1)
 9     {
10         //從串口接收數據後,判斷其是否為數字或字母,若是則加1後輸出
11         c = getc();
12         if(isDigit(c) || (isLetter(c)))
13             putc(c+1);
14     }
15     
16     return 0;
17 }
main.c

11.2.2 實例測試

1.PC上的串口工具推薦 Windows下推薦使用SecureCRT工具,Linux下推薦使用kermit。 下面介紹在Linux下安裝、使用kermit的方法。 確保Linux能上網,然後使用下面命令安裝,會安裝一個kermit命令。
$ sudo apt-get install ckermit
在使用kermit之前,先建立一個配置文件,在/home/book(假設用戶名為book)目錄下創 建名為.kermrc的文件,內容如下: 技術分享
 1 set line /dev/ttyS0
 2 set speed 115200
 3 set carrier-watch off
 4 set handshake none
 5 set flow-control none
 6 robust
 7 set file type bin
 8 set file name lit
 9 set rec  pack 1000
10 set send pack 1000
11 set window 5
配置kermrc 然後,運行“$ sudo kermit -c”命令即可開啟串口:要關閉串口,可以先輸入 “Ctrl+\”,然後按住“C”鍵,最後輸入“exit”後回車。 2. 測試方法 首先使用串口線將開發板的COM0和PC的串口連接,打開PC上的串口工具並設置其波 特率為115200、8N1。 然後,在uart目錄下運行make命令生成可執行文件uart.bin,將它燒入NAND Flash 中運行。 最後,在PC上串口工具中輸入數字或字母,可以看到輸出另一個字符(加了1):如果 輸入其他字符,則無輸出。 /work/hardware/stdio目錄下的程序在串口0上實現printf、scanf等函數,它使用 scanf、sscanf和printf等函數從串口接收一個十進制數字序列,然後將它轉換為十六進制 輸出。步驟與UART實例相似,讀者可自行操作。 附:代碼: 鏈接: https://pan.baidu.com/s/1kV24a9L 密碼: tfab

JZ2440 裸機驅動 第11章 通用異步收發器UART