新聞中心

        LPC1343串口學(xué)習(xí)

        作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò) 收藏
        本節(jié)我們來(lái)使用LPC1343的UART接口做一個(gè)簡(jiǎn)單的收發(fā)實(shí)驗(yàn)。

        大家之前應(yīng)該都有使用51或AVR一類(lèi)單片機(jī)做過(guò)異步串行收發(fā)實(shí)驗(yàn),當(dāng)然串口在電子開(kāi)發(fā)中的應(yīng)用地位就無(wú)需多言。我們直接進(jìn)入主題。

        本次試驗(yàn)這樣設(shè)計(jì),用PC作為上位機(jī)向UART發(fā)送一個(gè)(串)字節(jié),然后LPC1343收到這個(gè)(串)字節(jié)后再發(fā)回UART,在PC上的串口觀察軟件顯示出來(lái)。

        我們來(lái)看NXP帶給我們的UART例程來(lái)看看UART的設(shè)置以及工作過(guò)程。首先是主函數(shù):
        int main (void)
        {
        UARTInit(115200);//初始化UART接口并設(shè)置為波特率115200,NVIC也在內(nèi)一并設(shè)置
        while (1)
        {
        if ( UARTCount != 0 )
        {
        LPC_UART->IER = IER_THRE | IER_RLS;
        UARTSend( (uint8_t *)UARTBuffer, UARTCount );//發(fā)送數(shù)據(jù)
        UARTCount = 0;

        LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;
        }
        }
        }

        從主函數(shù)就可以看到本次例程的目的了:初始化UART——一旦接收到數(shù)據(jù)之后立即停止接收——發(fā)送——開(kāi)啟下一次接收。最重要的當(dāng)然是初始化函數(shù)UARTInit():

        void UARTInit(uint32_t baudrate)
        {
        uint32_t Fdiv;
        uint32_t regVal;

        UARTTxEmpty = 1;
        UARTCount = 0;

        NVIC_DisableIRQ(UART_IRQn); //關(guān)閉UART中斷,避免此后的初始化有中斷打斷
        LPC_IOCON->PIO1_6 &= ~0x07;
        LPC_IOCON->PIO1_6 |= 0x01;
        LPC_IOCON->PIO1_7 &= ~0x07;
        LPC_IOCON->PIO1_7 |= 0x01;

        LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
        LPC_SYSCON->UARTCLKDIV = 0x1;

        LPC_UART->LCR = 0x83;
        regVal = LPC_SYSCON->UARTCLKDIV;
        Fdiv=(((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)
        //baudrate ;

        LPC_UART->DLM = Fdiv / 256; //寫(xiě)入波特率計(jì)算值高位
        LPC_UART->DLL = Fdiv % 256; //寫(xiě)入波特率計(jì)算值低位
        LPC_UART->LCR = 0x03;
        LPC_UART->FCR = 0x07;

        regVal = LPC_UART->LSR;

        while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
        while ( LPC_UART->LSR & LSR_RDR )
        {
        regVal = LPC_UART->RBR;
        }


        NVIC_EnableIRQ(UART_IRQn);

        #if TX_INTERRUPT //是否使用發(fā)送中斷,本次例程使用
        LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;
        #else //所以執(zhí)行此else
        LPC_UART->IER = IER_RBR | IER_RLS;

        #endif
        return;
        }

        打星號(hào)的地方是筆者認(rèn)為比較值得關(guān)注的地方:
        1、UART的IO口設(shè)置,根據(jù)上述函數(shù)中的語(yǔ)句查找相關(guān)寄存器,可以發(fā)現(xiàn)它將P16、P17設(shè)置為:UART_RXD和UART_TXD功能;
        2、選擇UART時(shí)鐘分頻數(shù),此處1分頻,和波特率設(shè)置有直接關(guān)系;
        3、選擇數(shù)據(jù)格式,此處選擇數(shù)據(jù)長(zhǎng)度8位,無(wú)校驗(yàn),1位停止位,并開(kāi)啟除數(shù)鎖存;
        4、除數(shù)鎖存器:分為L(zhǎng)SB(8位)和MSB(8位),用來(lái)填入對(duì)應(yīng)某波特率的計(jì)數(shù)值,更改之前解除鎖定,更改完畢恢復(fù)鎖定,這樣就可以鎖定波特率了(可以這樣簡(jiǎn)單的理解);
        5、計(jì)算波特率,此處是重點(diǎn)了。首先我們肯定知道系統(tǒng)核心頻率為72MHz,即SystemCoreClock=72 000 000(參考本系列前幾章內(nèi)容)。而UART作為AHB總線上的設(shè)備,自然要經(jīng)過(guò)AHB分頻器,在此處,AHB分頻系數(shù)并未做過(guò)特別設(shè)置,所以為默認(rèn)值1。時(shí)鐘經(jīng)過(guò)AHB分頻之后要經(jīng)過(guò)UART分頻器進(jìn)行再分頻,分頻系數(shù)仍為1(第2點(diǎn))。因此我們來(lái)計(jì)算這個(gè)公式:
        Fdiv = (((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate
        其中SystemCoreClock=72000000,LPC_SYSCON->SYSAHBCLKDI=1,regVal=1,baudrate=115200,所以可以計(jì)算出:
        Fdiv=39.0625≈0x27
        這個(gè)便是產(chǎn)生115200波特率所要填入除數(shù)鎖存器的值。逆過(guò)來(lái)就可以計(jì)算出計(jì)數(shù)值對(duì)應(yīng)的波特率。
        6、線狀態(tài)寄存器(下文稍加講述)是以讀操作來(lái)清空的;
        其實(shí)這個(gè)函數(shù),對(duì)于用戶(hù)來(lái)說(shuō),只需要填入想要產(chǎn)生的波特率作為函數(shù)參數(shù)就可以完成LPC1343的UART初始化以及波特率設(shè)定工作。
        設(shè)定完成之后,UART就開(kāi)始工作了,因?yàn)槌跏蓟瘮?shù)里面開(kāi)啟了“啟用緩存數(shù)據(jù)可用中斷、線狀態(tài)中斷”所以當(dāng)有數(shù)據(jù)從上位機(jī)向UART發(fā)送數(shù)據(jù)時(shí),進(jìn)入中斷服務(wù)函數(shù):
        void UART_IRQHandler(void)
        {
        uint8_t IIRValue, LSRValue;
        uint8_t Dummy = Dummy;
        IIRValue = LPC_UART->IIR;
        IIRValue >>= 1;
        IIRValue &= 0x07;
        if (IIRValue == IIR_RLS)
        {
        LSRValue = LPC_UART->LSR;

        if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
        {

        UARTStatus = LSRValue;
        Dummy = LPC_UART->RBR;

        return;
        }
        if (LSRValue & LSR_RDR)
        {

        UARTBuffer[UARTCount++] = LPC_UART->RBR;
        if (UARTCount == BUFSIZE)
        {
        UARTCount = 0;
        }
        }
        }
        else if (IIRValue == IIR_RDA)
        {

        UARTBuffer[UARTCount++] = LPC_UART->RBR;
        if (UARTCount == BUFSIZE)
        {
        UARTCount = 0;
        }
        }
        else if (IIRValue == IIR_CTI)
        {

        UARTStatus |= 0x100;
        }
        else if (IIRValue == IIR_THRE)
        {

        LSRValue = LPC_UART->LSR;
        if (LSRValue & LSR_THRE)
        {
        UARTTxEmpty = 1;
        }
        else
        {
        UARTTxEmpty = 0;
        }
        }
        return;
        }
        這個(gè)中斷服務(wù)函數(shù)是一個(gè)if…else if….else if結(jié)構(gòu)。在進(jìn)入此中斷服務(wù)函數(shù)后,讀取

        中斷標(biāo)識(shí)寄存器判斷中斷源,選擇進(jìn)入相應(yīng)的if環(huán)節(jié)執(zhí)行相應(yīng)語(yǔ)句。我們看看UART都有哪些中斷。第一個(gè)是RLS,Receive Line Status即接收線中斷:
        可以在用戶(hù)手冊(cè)查看到接受線中斷分別有以下多種:
        RDR :Receiver Data Ready,接受數(shù)據(jù)就緒中斷;
        OE:Overrun Error,即溢出錯(cuò)誤中斷;
        PE:Parity Error,校驗(yàn)錯(cuò)誤中斷;
        FE:Framing Error,幀錯(cuò)誤中斷;
        BI:Break Interrupt,間隔狀態(tài)中斷;
        THRE:Transmitter Holding Register Empty,發(fā)送保持寄存器空中斷;
        TEMP:Transmitter Empty,發(fā)送保持寄存器與臨時(shí)寄存器空中斷;
        RXFE:Error in RX FIFO,RX錯(cuò)誤中斷;
        對(duì)照上述中斷服務(wù)函數(shù)第一個(gè)if部分,當(dāng)判斷確定為線中斷之后,即判斷是否是OE——RXFE中的任何一個(gè)錯(cuò)誤,如果有錯(cuò)誤,則讀出數(shù)據(jù)有效保存,如果有錯(cuò)誤,則讀出數(shù)據(jù)但丟棄。
        所以,線中斷在進(jìn)行數(shù)據(jù)校驗(yàn)的場(chǎng)合才會(huì)使用。而本次實(shí)驗(yàn)中并未用到數(shù)據(jù)校驗(yàn)位。所以此中斷不會(huì)進(jìn)入。
        當(dāng)不使用校驗(yàn)功能之時(shí),收到數(shù)據(jù)之后會(huì)進(jìn)入第一個(gè)else if結(jié)構(gòu):
        else if (IIRValue == IIR_RDA)
        {}
        在進(jìn)入此部分之后將數(shù)據(jù)讀出。
        當(dāng)接受一個(gè)字符(5~8位不等)超時(shí)時(shí),會(huì)進(jìn)入“接受字符超時(shí)中斷”部分。
        發(fā)送完成中斷在本次試驗(yàn)中并未使能,略過(guò)。
        如此我們應(yīng)該可以預(yù)知本次試驗(yàn)中當(dāng)PC上位機(jī)發(fā)送一個(gè)(串)字符之后,會(huì)進(jìn)入中斷服務(wù)函數(shù)并且進(jìn)入else if (IIRValue == IIR_RDA{}環(huán)節(jié),將收到的數(shù)據(jù)保存在UARTBuffer中,并使UARTCount++。然后退出中斷函數(shù)之后,回到主函數(shù),執(zhí)行發(fā)送部分:
        if ( UARTCount != 0 )
        {
        LPC_UART->IER = IER_THRE | IER_RLS;
        UARTSend( (uint8_t *)UARTBuffer, UARTCount );//發(fā)送數(shù)據(jù)
        UARTCount = 0;

        LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;
        }
        }
        找到UARTSend():
        void UARTSend(uint8_t *BufferPtr, uint32_t Length)
        {
        while ( Length != 0 )
        {

        #if !TX_INTERRUPT//未使用中斷發(fā)送方式,所以編譯此部分
        while ( !(LPC_UART->LSR & LSR_THRE) );//等待發(fā)送保持寄存器空
        LPC_UART->THR = *BufferPtr;//將待發(fā)數(shù)據(jù)寫(xiě)入發(fā)送保持寄存器
        #else

        while ( !(UARTTxEmpty & 0x01) );
        LPC_UART->THR = *BufferPtr;
        UARTTxEmpty = 0;
        #endif
        BufferPtr++;
        Length--;
        }
        return;
        }
        此UART數(shù)據(jù)發(fā)送函數(shù),第一個(gè)參數(shù)要求填入存放待發(fā)送數(shù)據(jù)(注意為8位,即字符型數(shù)據(jù))的數(shù)組名,第二個(gè)參數(shù)為待發(fā)數(shù)據(jù)長(zhǎng)度。通過(guò)注釋可以看到發(fā)送的過(guò)程很簡(jiǎn)單,等待發(fā)送保持寄存器為空后將數(shù)據(jù)寫(xiě)入發(fā)送保持寄存器就完成了發(fā)送。
        這樣我們就將本次的UART收發(fā)試驗(yàn)的過(guò)程“初始化——等待接收——UART中斷——保存數(shù)據(jù)——發(fā)送數(shù)據(jù)”分析完畢。
        NXP贈(zèng)送的這個(gè)LPC1343并沒(méi)有掛載UART接口,而只留了P16、P17兩個(gè)IO給用戶(hù)拓展,所以筆者使用了其他開(kāi)發(fā)板的串口連接,需要注意的是,我們手上的這塊開(kāi)發(fā)板是3.3V供電,而市面上比較多采用的MAX232是5V供電。所以或者使用LPC1343評(píng)估板的5V給MAX232供電,或者使用3.3V供電的電平轉(zhuǎn)換芯片。筆者這里使用了3.3V供電的ST232芯片。
        導(dǎo)入lpc1343.examples->uart,編譯鏈接。連好硬件,從串口調(diào)試終端發(fā)送一個(gè)(串)數(shù)據(jù),可以看到串口調(diào)試終端的接收框里準(zhǔn)確的顯示了我們所發(fā)送的數(shù)據(jù),本次實(shí)驗(yàn)完結(jié)。


        關(guān)鍵詞: LPC1343串口學(xué)

        評(píng)論


        技術(shù)專(zhuān)區(qū)

        關(guān)閉
        主站蜘蛛池模板: 桂东县| 衢州市| 会宁县| 中超| 枣庄市| 轮台县| 右玉县| 江津市| 东乌| 凤翔县| 山东| 江华| 塘沽区| 德安县| 苏州市| 磐石市| 石河子市| 马公市| 威信县| 娄底市| 乌拉特中旗| 北碚区| 准格尔旗| 伽师县| 封丘县| 图们市| 上思县| 文安县| 长岛县| 镇沅| 姜堰市| 罗甸县| 喀喇沁旗| 孝感市| 遵义市| 石河子市| 虹口区| 绍兴县| 安丘市| 慈溪市| 嵊泗县|