ESP8266學(xué)習(xí)筆記(9)——UART串口使用(NONOS SDK)

一、簡(jiǎn)介

ESP8266 有兩個(gè)UART。UART0有TX、RX作為 系統(tǒng)的打印信息輸出接口數(shù)據(jù)收發(fā)口,而UART1只有TX,作為 打印信息輸出接口(調(diào)試用)。

二、UART0接收

2.1 相關(guān)函數(shù)

/driver/uart.c 中,

2.1.1 uart0_rx_intr_handler

用于UART0中斷處理,用戶可在該函數(shù)內(nèi)添加對(duì)接收到數(shù)據(jù)包的處理。

LOCAL void
uart0_rx_intr_handler(void *para)
{
    /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
    * uart1 and uart0 respectively
    */
    uint8 RcvChar;
    uint8 uart_no = UART0;//UartDev.buff_uart_no;
    uint8 fifo_len = 0;
    uint8 buf_idx = 0;
    uint8 temp,cnt;
    //RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;

    /* 注意: */
    // 不要在中斷處理函數(shù)中調(diào)用帶有 "ICACHE_FLASH_ATTR" 宏的函數(shù),否則將引起異常。
    /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
    /*IF NOT , POST AN EVENT AND PROCESS IN SYSTEM TASK */

    // 接收幀錯(cuò)誤中斷
    if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);    // 清除中斷寄存器的 幀錯(cuò)誤位
    }
    // 接收滿中斷 FULL
    else if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
    {
        uart_rx_intr_disable(UART0);                                    // 1. 接收中斷禁用,用于不再接受數(shù)據(jù),因?yàn)楝F(xiàn)在處于處理數(shù)據(jù)中
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);  // 2.清除中斷寄存器的 接收 FULL 位
        system_os_post(uart_recvTaskPrio, 0, 0);                        // 3.向任務(wù)函數(shù)發(fā)送消息
    }
    // 接收超時(shí)中斷 TOUT
    else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
    {
        uart_rx_intr_disable(UART0);                                    // 1. 接收中斷禁用,用于不再接受數(shù)據(jù),因?yàn)楝F(xiàn)在處于處理數(shù)據(jù)中
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);  // 2.清除中斷寄存器的 接收超時(shí)中斷位
        system_os_post(uart_recvTaskPrio, 0, 0);                        // 3.向任務(wù)函數(shù)發(fā)送消息
    }
    // 發(fā)送 FIFO 空中斷
    else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST))
    {
        /* to output uart data from uart buffer directly in empty interrupt handler*/
        /*instead of processing in system event, in order not to wait for current task/function to quit */
        /*ATTENTION:*/
        /*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/
        /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
        CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);// 清楚中斷標(biāo)志
        //system_os_post(uart_recvTaskPrio, 1, 0);
        WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);  // 清除中斷寄存器的 發(fā)送 FIFO 空中斷位
    }
    // 接收溢出中斷
    else if(UART_RXFIFO_OVF_INT_ST  == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR); // 清除中斷寄存器的 接收溢出中斷位
    }
}

2.1.2 uart_recvTask

上述uart0_rx_intr_handler函數(shù)中,在滿中斷和超時(shí)中斷時(shí),system_os_post發(fā)送了一個(gè)信號(hào),于是進(jìn)入uart_recvTask函數(shù)。

LOCAL void ICACHE_FLASH_ATTR
uart_recvTask(os_event_t *events)
{
    if(events->sig == 0)
    {
        // 1.從先進(jìn)先出通道 FIFO 讀取接收到的數(shù)據(jù)長(zhǎng)度
        uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;

        uint8 d_tmp = 0;
        uint8 idx = 0;
        // 2.定義一個(gè)臨時(shí)接收的數(shù)據(jù)區(qū)
        uint8 uartRxBuffer[256] = {0};

        // 3. 賦值給臨時(shí)數(shù)組
        for(idx = 0; idx < fifo_len; idx++) 
        {
            d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;   // 根據(jù)數(shù)據(jù)長(zhǎng)度一個(gè)一個(gè)讀取數(shù)據(jù)
            uartRxBuffer[idx] = d_tmp;                        // 賦值
        }
              
        // 4.做你自己的事情,uartRxBuffer[]數(shù)組就是接收到的數(shù)據(jù)
        {
            ...
            ...
        }

        // 清除中斷寄存器的 滿中斷位 或 超時(shí)中斷位
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);  
        // 5.UART0接收中斷使能
        uart_rx_intr_enable(UART0);
    }
    else if(events->sig == 1)
    {
    }
}

2.2 使用流程

①串口初始化
uart_init(115200, 115200); // 設(shè)置串口0和串口1的波特率
②串口中斷處理
uart0_rx_intr_handler(void *para); // UART0 中斷處理函數(shù),在此用作中斷觸發(fā)類型的判斷
主要修改下面這個(gè)函數(shù)
uart_recvTask(os_event_t *events) // UART0 中斷處理函數(shù),在此用作中斷接收數(shù)據(jù)處理

三、UART0發(fā)送

3.1 相關(guān)函數(shù)

3.2 使用流程

①串口初始化
uart_init(115200, 115200); // 設(shè)置串口0和串口1的波特率
②串口發(fā)送數(shù)據(jù)
uart0_tx_buffer(void *buf, uint16 len); // UART0 發(fā)送數(shù)據(jù)函數(shù)

四、UART1發(fā)送

4.1 相關(guān)函數(shù)

/driver/uart.c 中,

4.1.1 UART_SetPrintPort

用于設(shè)置打印調(diào)試信息的串口

void ICACHE_FLASH_ATTR
UART_SetPrintPort(uint8 uart_no)
{
    if(uart_no==1){
        os_install_putc1(uart1_write_char);
    }else{
        /*option 1: do not wait if uart fifo is full,drop current character*/
        os_install_putc1(uart0_write_char_no_wait);
    /*option 2: wait for a while if uart fifo is full*/
    os_install_putc1(uart0_write_char);
    }
}

4.1.2 uart1_sendStr_no_wait

用于串口1輸出一串字符

void uart1_sendStr_no_wait(const char *str)
{
    while(*str){
        uart_tx_one_char_no_wait(UART1, *str++);
    }
}

3.2 使用流程

①串口初始化
uart_init(115200, 115200); // 設(shè)置串口0和串口1的波特率
②設(shè)置調(diào)試串口
UART_SetPrintPort(UART1); // 使用串口1打印調(diào)試信息
③打印調(diào)試信息
os_printf()uart1_sendStr_no_wait()


? 由 Leung 寫于 2019 年 2 月 16 日

? 參考:Esp8266 進(jìn)階之路25【高級(jí)篇】深聊下esp8266的串口 Uart 通訊中斷編程
    ESP8266 Non-OS SDK API參考[7qq6]
    ESP8266 技術(shù)參考[zj5o]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容