新聞中心

        s3c2440的UART用法

        作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
        SPI、IIC和UART是最常用的三種串行總線,這三種總線在s3c2440中都被集成了。在這里我們主要介紹UART,另兩個(gè)總線在后面的文章中給出。

        UART(Universal Asynchronous Receiver/Transmitter,通用異步接收/發(fā)送裝置)用于異步通信,可以實(shí)現(xiàn)全雙工發(fā)送和接收。它不僅可以實(shí)現(xiàn)不同嵌入式系統(tǒng)之間的通信,還可以實(shí)現(xiàn)與PC之間的通信。

        s3c2440提供了三個(gè)UART端口,它們都可以通過(guò)查詢、中斷和DMA方式傳輸數(shù)據(jù),而且每個(gè)UART都分別有一個(gè)64個(gè)字節(jié)的接收FIFO和一個(gè)64個(gè)字節(jié)的發(fā)送FIFO。在這里,我們只給出非FIFO模式,即傳輸數(shù)據(jù)不利用FIFO緩存,一個(gè)字節(jié)一個(gè)字節(jié)地傳輸。

        下面我們就給出如何用s3c2440來(lái)實(shí)現(xiàn)非FIFO的UART通信。要實(shí)現(xiàn)某種通信,就必須遵循該通信協(xié)議。UART的協(xié)議包括傳輸數(shù)據(jù)的位數(shù),停止位的位數(shù),以及是否進(jìn)行奇偶校驗(yàn),這些設(shè)置是利用ULCONn寄存器完成的。另一個(gè)很重要的地方就是設(shè)置波特率。s3c2440波特率的時(shí)鐘源有三個(gè):PCLK、FCLK/n和UEXTCLK。時(shí)鐘源的選擇是由UCONn的第10位和第11位來(lái)完成的。波特率的具體計(jì)算公式為:
        時(shí)鐘源頻率÷(波特率×16)-1
        這個(gè)計(jì)算結(jié)果很可能是小數(shù),把該小數(shù)取最接近的整數(shù),放入寄存器UBRDIVn中就完成了波特率的設(shè)置。如我們選擇波特率的時(shí)鐘源為PCLK,它為50MHz,我們?cè)O(shè)置的波特率為115.2kHz,通過(guò)上式計(jì)算的結(jié)果為26.13,取整后得到26,那么我們把26放入U(xiǎn)BRDIVn中即可。由于我們沒有使用FIFO和MODEM,所以可以不用設(shè)置FIFO控制寄存器UFCONn和MODEM控制寄存器UMCONn。通過(guò)以上寄存器的設(shè)置,UART就可以正常傳輸數(shù)據(jù)。

        接收到的數(shù)據(jù)是放到接收緩存器URXHn中,要發(fā)送數(shù)據(jù)時(shí),是把數(shù)據(jù)放入發(fā)送緩存器UTXHn中。由于UART是通過(guò)字節(jié)方式傳輸數(shù)據(jù)的,因此要區(qū)分是大端模式還是小端模式,也就是說(shuō)這兩個(gè)寄存器在這兩種模式下,所在的地址是不同。為了了解當(dāng)前數(shù)據(jù)傳輸?shù)母鞣N狀態(tài),還需要一些狀態(tài)寄存器。傳輸狀態(tài)寄存器UTRSTATn非常有用,它的第0位可以用來(lái)判斷接受緩存器內(nèi)是否有可接收的數(shù)據(jù),第1位和第2位可以用來(lái)判斷發(fā)送緩存器中是否為空,為空時(shí)可以發(fā)送數(shù)據(jù)。由于在這里我們不進(jìn)行傳輸數(shù)據(jù)時(shí)錯(cuò)誤的判斷,因此錯(cuò)誤狀態(tài)寄存器UERSTATn不需要,F(xiàn)IFO狀態(tài)寄存器UFSTATn和MODEM狀態(tài)寄存器UMSTATn在這里也不需要。

        我們給出UART通信的兩種方法:查詢和中斷。為了驗(yàn)證程序,使用任一款的串行通信軟件來(lái)實(shí)現(xiàn)PC和s3c2440之間的通信即可。

        首先給出的是查詢程序。它是在主程序的循環(huán)體內(nèi)不斷查詢UART端口,當(dāng)有數(shù)據(jù)來(lái)時(shí),就接收數(shù)據(jù),并再通過(guò)UART發(fā)送該數(shù)據(jù)。然后根據(jù)所接收數(shù)據(jù)的不同,分別執(zhí)行不同的內(nèi)容,如點(diǎn)亮、熄滅LED,蜂鳴器響、或不響。在這里,我們每次只完成一個(gè)字節(jié)的傳輸。

        #define rGPBCON(*(volatile unsigned *)0x56000010)//Port B control
        #define rGPBDAT(*(volatile unsigned *)0x56000014)//Port B data
        #define rGPBUP(*(volatile unsigned *)0x56000018)//Pull-up control B

        #define rGPHCON(*(volatile unsigned *)0x56000070)//Port H control
        #define rGPHUP(*(volatile unsigned *)0x56000078)//Pull-up control H

        #define rULCON0(*(volatile unsigned *)0x50000000)//UART 0 Line control
        #define rUCON0(*(volatile unsigned *)0x50000004)//UART 0 Control
        #define rUFCON0(*(volatile unsigned *)0x50000008)//UART 0 FIFO control
        #define rUMCON0(*(volatile unsigned *)0x5000000c)//UART 0 Modem control
        #define rUTRSTAT0(*(volatile unsigned *)0x50000010)//UART 0 Tx/Rx status
        #define rUERSTAT0(*(volatile unsigned *)0x50000014)//UART 0 Rx error status
        #define rUFSTAT0(*(volatile unsigned *)0x50000018)//UART 0 FIFO status
        #define rUMSTAT0(*(volatile unsigned *)0x5000001c)//UART 0 Modem status
        #define rUBRDIV0(*(volatile unsigned *)0x50000028)//UART 0 Baud rate divisor

        //little endian
        #define rUTXH0 (*(volatile unsigned char *)0x50000020)//UART 0 Transmission Hold
        #define rURXH0 (*(volatile unsigned char *)0x50000024)//UART 0 Receive buffer

        void Main(void)
        {
        char ch;
        rGPBCON = 0x015551;
        rGPBUP= 0x7ff;
        rGPBDAT = 0x1e0;

        rGPHCON = 0x00faaa;//使用UART0功能
        rGPHUP= 0x7ff;

        rULCON0 = 0x3;//設(shè)置UART0無(wú)奇偶校驗(yàn),一位停止位,8位數(shù)據(jù)
        rUCON0 = 0x245;//PCLK為時(shí)鐘源,接收和發(fā)送數(shù)據(jù)為查詢或中斷方式
        rUFCON0 = 0;//
        rUMCON0 = 0;//
        rUBRDIV0 = 26;//設(shè)置波特率,PCLK為50MHz,波特率為115.2kHz

        while(!(rUTRSTAT0 & 0x2));//等待并判斷發(fā)送緩存是否為空
        rUTXH0 = 0xaa;//是空,則發(fā)送0xAA字節(jié)

        while(1)
        {
        while(!(rUTRSTAT0 & 0x1)); //等待并判斷接收緩存是否準(zhǔn)備好
        ch = rURXH0;//接收一個(gè)字節(jié)數(shù)據(jù)
        while(!(rUTRSTAT0 & 0x2));//等待并判斷發(fā)送緩存是否為空
        rUTXH0 = ch;//發(fā)送一個(gè)字節(jié)數(shù)據(jù)

        switch(ch)//根據(jù)所接收數(shù)據(jù)的不同,執(zhí)行不同的程序
        {
        case 0x11://滅LED
        rGPBDAT |= 0x1e0;
        break;
        case 0x22://亮LED
        rGPBDAT &= 0x1f;
        break;
        case 0x33://蜂鳴器不響
        rGPBDAT &= 0x1e0;
        break;
        case 0x44://蜂鳴器響
        rGPBDAT |= 0x1;
        break;
        default://LED滅,蜂鳴器不響
        rGPBDAT = 0x1e0;
        break;
        }
        }
        }

        下面是UART中斷程序,它要比查詢復(fù)雜一些,因?yàn)樯婕暗搅酥袛嗵幚?,并且UART發(fā)送數(shù)據(jù)和接收數(shù)據(jù)是一個(gè)中斷源。主程序循環(huán)體內(nèi)不執(zhí)行任何程序,都在UART中斷程序內(nèi)執(zhí)行。當(dāng)接收到0x55字節(jié)數(shù)據(jù)時(shí),亮兩個(gè)LED,當(dāng)接收到其他數(shù)據(jù)時(shí),發(fā)送該字節(jié),并在發(fā)送部分執(zhí)行亮4個(gè)LED程序。


        #define _ISR_STARTADDRESS 0x33ffff00
        #define pISR_UART0(*(unsigned *)(_ISR_STARTADDRESS+0x90))
        #define U32 unsigned int

        #define rGPBCON(*(volatile unsigned *)0x56000010)//Port B control
        #define rGPBDAT(*(volatile unsigned *)0x56000014)//Port B data
        #define rGPBUP(*(volatile unsigned *)0x56000018)//Pull-up control B

        #define rGPHCON(*(volatile unsigned *)0x56000070)//Port H control
        //#define rGPHDAT(*(volatile unsigned *)0x56000074)//Port H data
        #define rGPHUP(*(volatile unsigned *)0x56000078)//Pull-up control H

        #define rULCON0(*(volatile unsigned *)0x50000000)//UART 0 Line control
        #define rUCON0(*(volatile unsigned *)0x50000004)//UART 0 Control
        #define rUFCON0(*(volatile unsigned *)0x50000008)//UART 0 FIFO control
        #define rUMCON0(*(volatile unsigned *)0x5000000c)//UART 0 Modem control
        #define rUTRSTAT0(*(volatile unsigned *)0x50000010)//UART 0 Tx/Rx status
        #define rUERSTAT0(*(volatile unsigned *)0x50000014)//UART 0 Rx error status
        #define rUFSTAT0(*(volatile unsigned *)0x50000018)//UART 0 FIFO status
        #define rUMSTAT0(*(volatile unsigned *)0x5000001c)//UART 0 Modem status
        #define rUBRDIV0(*(volatile unsigned *)0x50000028)//UART 0 Baud rate divisor

        //little endian
        #define rUTXH0 (*(volatile unsigned char *)0x50000020)//UART 0 Transmission Hold
        #define rURXH0 (*(volatile unsigned char *)0x50000024)//UART 0 Receive buffer


        #define rSRCPND(*(volatile unsigned *)0x4a000000)//Interrupt request status
        #define rINTMSK(*(volatile unsigned *)0x4a000008)//Interrupt mask control
        #define rINTPND(*(volatile unsigned *)0x4a000010)//Interrupt request status
        #define rSUBSRCPND(*(volatile unsigned *)0x4a000018)//Sub source pending
        #define rINTSUBMSK(*(volatile unsigned *)0x4a00001c)//Interrupt sub mask

        void __irq uartISP(void)
        {
        char ch;

        rSUBSRCPND |= 0x3;
        rSRCPND = 0x1<<28;
        rINTPND = 0x1<<28;

        if(rUTRSTAT0 & 1)//接收數(shù)據(jù)處理部分
        {
        ch = rURXH0;//接收字節(jié)數(shù)據(jù)
        if(ch==0x55)
        rGPBDAT = ~0x61;//亮兩個(gè)LED
        else
        rUTXH0 = ch;//發(fā)送字節(jié)數(shù)據(jù)
        }
        else//發(fā)送數(shù)據(jù)處理部分
        {
        rGPBDAT = ~0x1e1;//亮4個(gè)LED
        }
        }

        void Main(void)
        {

        rGPBCON = 0x015551;
        rGPBUP= 0x7ff;
        rGPBDAT = 0x1e0;

        rGPHCON = 0x00faaa;
        rGPHUP= 0x7ff;

        rULCON0 = 0x3;
        rUCON0 = 0x5;
        rUFCON0 = 0;
        rUMCON0 = 0;
        rUBRDIV0 = 26;

        rSRCPND = 0x1<<28;
        rSUBSRCPND = 0x3;
        rINTPND = 0x1<<28;
        rINTSUBMSK = ~(0x3);//打開UART0發(fā)送和接收中斷屏蔽
        rINTMSK = ~(0x1<<28);//打開UART0中斷屏蔽

        pISR_UART0 = (U32)uartISP;

        while(1)
        {

        }
        }

        最后還要強(qiáng)調(diào)幾點(diǎn)關(guān)于非FIFO模式下UART中斷的一些注意事項(xiàng):
        1.對(duì)于s3c2440來(lái)說(shuō),接收數(shù)據(jù)是被動(dòng)的,發(fā)送數(shù)據(jù)是主動(dòng)的,因此一般來(lái)說(shuō),接收數(shù)據(jù)用中斷方式,發(fā)送數(shù)據(jù)用查詢方式較好;
        2.在中斷方式下,當(dāng)接收到數(shù)據(jù)時(shí),盡管可能該數(shù)據(jù)無(wú)用,但也一定要讀取它,否則下次再接收數(shù)據(jù)時(shí),不會(huì)再引起中斷,因?yàn)榻邮諗?shù)據(jù)緩存器被上次接收到的數(shù)據(jù)所霸占,只要沒有讀取它,它就永遠(yuǎn)在那里;
        3.由于UART中斷涉及到SUBSRCPND寄存器,因此在中斷處理程序中不僅要清SRCPND寄存器,還要清SUBSRCPND寄存器,它們的順序一定是先清SUBSRCPND寄存器,再清SRCPND寄存器,否則就會(huì)引起一個(gè)中斷兩次響應(yīng)的問題。因?yàn)槭欠裰袛嘤蒘RCPND寄存器決定,而SRCPND寄存器的相關(guān)狀態(tài)位由SUBSRCPND寄存器決定,如果先清SRCPND寄存器,而還沒有清SUBSRCPND寄存器的話,SRCPND寄存器的相關(guān)位還是會(huì)被置1,而一旦被置1,則一定還會(huì)引起中斷。


        關(guān)鍵詞: s3c2440UART用

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 泗水县| 平武县| 泗阳县| 芜湖县| 三原县| 蒲江县| 陵水| 常熟市| 桃江县| 闽侯县| 九江县| 大竹县| 贵州省| 灵丘县| 阿尔山市| 遂溪县| 靖江市| 汤原县| 玉屏| 昌江| 蓬溪县| 桐庐县| 华亭县| 昌宁县| 荔浦县| 锡林郭勒盟| 孙吴县| 东兰县| 阿巴嘎旗| 云浮市| 右玉县| 巴中市| 白沙| 克什克腾旗| 湄潭县| 甘泉县| 托里县| 扎兰屯市| 莲花县| 宁波市| 沭阳县|