新聞中心

        第4課:UART串口編程

        作者: 時間:2016-11-11 來源:網(wǎng)絡(luò) 收藏
        首先明確一點:我們學(xué)習(xí)的串口是異步串口。在傳輸時,他們各自有各自的時鐘。就是我們說的波特率。

        我們學(xué)習(xí)的RS232與UART的區(qū)別是,UART使用標(biāo)準(zhǔn)的TTL/COMS電平 進過一個芯片使它的高低電平從TTL中0與3.3V 變成了 低電平5v到15v

        本文引用地址:http://www.104case.com/article/201611/316803.htm

        高電平-3v到-12v。

        首先說一下串口的數(shù)據(jù)幀格式。它由一個開始位,數(shù)據(jù)位,校驗位和停止位組成。

        平時數(shù)據(jù)處于1狀態(tài)。

        當(dāng)要開始發(fā)送時,從UART改變TxD數(shù)據(jù)變成0狀態(tài)1個位的時間,在接受端到0之后的1.5位的時間,接收端開始接受數(shù)據(jù)。

        數(shù)據(jù)位分為5,6,7,8。四種類型的數(shù)據(jù)位。之后就是校驗位站1位,可以設(shè)置也可以不設(shè)置。最后的是停止位。可以是1位,1.5位,2位。這個是高電平1。

        UART可以用中斷或DMA來工作。它有3個單獨的通道。它由4部分組成,發(fā)送器,接收器,波特率發(fā)生器,控制邏輯組成。

        這些部分的設(shè)置都是通過寄存器來實現(xiàn)的。

        發(fā)送的過程是這樣的,UART只能通過shifter一位一位的來發(fā)數(shù)據(jù)。它先把要發(fā)的數(shù)據(jù)放到它的緩存FIFO里,當(dāng)然緩存也可以取消。然后放入shifter里面來發(fā)出去。接受也是一樣的。通過緩存來接受,然后再通過接受的shifter來接。

        具體繼電器的設(shè)置主要由以下幾個:

        ULCON 邏輯數(shù)據(jù)楨格式控制器

        UCON 串口的控制繼電器

        UFCON FIFO控制寄存器

        UMCON 串口MODEN控制器 (可以控制AFC 自動流控制)

        以下是狀態(tài)寄存器,用來確定狀態(tài)的,比如說shifter發(fā)送器的狀態(tài),接收器的狀態(tài)。

        UTRSTAT 接受發(fā)送控制器

        UERSTAT 錯誤狀態(tài)寄存器

        UFSTAT FIFO狀態(tài)寄存器

        最后一個單獨的設(shè)置寄存器,它用來設(shè)置波特率

        UBRDIV 波特率發(fā)生器

        以下來寫個簡單的串口例子。

        它不使用FIFO 中斷 而直接用shifter收發(fā),采用輪詢的方式來檢測數(shù)據(jù)是否發(fā)送或被接受。然后通過minicom向開發(fā)板發(fā)送1表示亮燈,發(fā)送2表示熄燈。

        文件總共是7個 一個crt0.s main.c addr.h uart.h uart.c uart.lds makefile

        crt0.s 是關(guān)閉watchdog 并跳轉(zhuǎn)到mian 之后用個deadloop。

        .text
        .globl _start
        _start:
        ldrr0, =0x53000000 @ WATCHDOG close
        movr1, #0x0
        strr1, [r0]
        ldr sp, =1024*4 @set stack,but the capitcy of cache is only 4k

        bl main
        halt_loop:
        b halt_loop

        第2個是addr.h用來寫寄存器的宏定義。

        #ifndef ADDR_H
        #define ADDR_H
        #define GPECON (*(volatile unsigned int *)0x56000040)
        #define GPEDAT (*(volatile unsigned int *)0x56000044)

        #define GPE12_out (1<<(12*2))
        #define GPE13_out (1<<(13*2))

        #define GPHCON (*(volatile unsigned int *)0x56000070)
        #define GPHUP (*(volatile unsigned int *)0x56000074)
        #define ULCON0 (*(volatile unsigned int *)0x50000000)
        #define UCON0 (*(volatile unsigned int *)0x50000004)
        #define UFCON0 (*(volatile unsigned int *)0x50000008)
        #define UMCON0 (*(volatile unsigned int *)0x5000000C)
        #define UTRSTAT0 (*(volatile unsigned int *)0x50000010)
        #define UFSTAT0 (*(volatile unsigned int *)0x50000018)
        #define UTXH0 (*(volatile unsigned int *)0x50000020)
        #define URXH0 (*(volatile unsigned int *)0x50000024)
        #define UBRDIV0 (*(volatile unsigned int *)0x50000028)

        #endif

        第3個文件來寫uart.h,這是個我們的功能

        #ifndef UART_H
        #define UART_H
        void uart_init(); //初始化繼電器

        void uart_write(char *a); //串口寫一行

        void uart_read(char *a,int n);//串口讀n個字

        void uart_read_line(char *a); //讀一行

        void led_on(); //開燈

        void led_off();//關(guān)燈
        #endif

        第4個文件具體來寫uart.C

        #include"uart.h"
        #include"addr.h"
        #define UART_CLK 50000000 //我們用的是PCLK 50MHz
        #define UART_BAUD_RATE 115200 //比特率是115200
        #define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1 //計算公式的宏
        void uart_init()
        {
        GPHCON |=0xa0;//這個是TXD0與RXD0的設(shè)置,他們用的是GPH2和3復(fù)用的特殊
        GPHUP = 0x0c;//功能,所以還要在這設(shè)置上拉電阻,以區(qū)別高低電平的。
        ULCON0 = 0x3; //楨格式的設(shè)置8個數(shù)據(jù)位,無校驗
        UCON0 = 0x5;//選擇的是中斷與輪詢模式
        UFCON0 = 0;//不設(shè)FIFO
        UMCON0 = 0;//不設(shè)AFC
        UBRDIV0 = UART_BRD; //設(shè)置波特率
        }

        void uart_write(char *a)
        {
        do{
        while(!(UTRSTAT0&2)); //UTRSTAT0的第2位是1的話表示發(fā)送數(shù)據(jù)的shifter內(nèi)的數(shù)據(jù)已經(jīng)被發(fā)送了,現(xiàn)在數(shù)據(jù)為空。如果里面的數(shù)據(jù)沒有空的話!(U&2)會一直是1,造成一直循環(huán),知道出現(xiàn)UTRSTAT0第2位為1的情況。

        UTXH0 = *(a++); //發(fā)送寄存器只能一次最多發(fā)8位
        }
        while(*a!=

        主站蜘蛛池模板: 临颍县| 克什克腾旗| 郧西县| 吴堡县| 延川县| 丹江口市| 武清区| 东兰县| 仲巴县| 鸡西市| 吉安县| 英德市| 泸定县| 安顺市| 山东| 西和县| 榆社县| 天水市| 稷山县| 闵行区| 二连浩特市| 新野县| 石楼县| 松桃| 平乐县| 正镶白旗| 都兰县| 修文县| 平湖市| 云南省| 兴和县| 青神县| 西青区| 临朐县| 德格县| 湟源县| 共和县| 深水埗区| 峨边| 墨玉县| 马龙县|