zoukankan      html  css  js  c++  java
  • ESP8266 SDK开发: 外设篇-串口

    串口分布

      

    NONOS

    NONOS

    NONOS

    1.配置串口

    2.按照上面的配置以后,接收中断进入这里面

    3.用户需要知道的事情

    串口内部自带一个FIFO缓存,数据接收以后先缓存到内部FIFO缓存里面

    内部FIFO满了以后进入FIFO满中断

    串口打开了串口超时(空闲)中断:超过两个字节的时间没有接受到数据,进入串口超时(空闲)中断

    接收思路:

    如果进入满中断,在满中断中提取FIFO里面的数据

    如果进入空闲中断,在空闲中断中提取FIFO里面的数据

    无论怎样,程序最终都会进入空闲中断!

    这节接收数据采用缓存

    具体细节请参考:

    https://www.cnblogs.com/yangfengwu/p/12770504.html

    4.直接上菜

    4.1创建缓存

    #include "driver/BufferManage.h"
    /*******串口接收缓存********/
    #define UartReadbuffLen 2048
    #define UartManagebuffLen 60
    u8  UartReadbuff[UartReadbuffLen];//缓存串口接收的每一条数据
    u32 UartManagebuff[UartManagebuffLen];//最大管理的数据条数
    
    u8  UartReadbuffCopy[UartReadbuffLen];//提取缓存数据
    
    
    
    BufferManageCreate(&buff_manage, UartReadbuff, UartReadbuffLen, UartManagebuff, UartManagebuffLen*4);//创建缓存

    4.2往缓存里面存数据

    #include "driver/BufferManage.h"
    
    #define Uart0ReadBuffLen 2048
    uint8 Uart0ReadBuff[Uart0ReadBuffLen];//串口一次性最大接收的数据个数
    u32   Uart0ReadCnt=0;
    
    
    
    LOCAL void
    uart0_rx_intr_handler(void *para)
    {
        uint8 RcvChar;
        uint8 uart_no = UART0;//UartDev.buff_uart_no;
        uint8 fifo_len = 0;
        uint8 buf_idx = 0;
        uint8 temp,cnt;
        int WriteState;
        //RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
        
        if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)){
            DBG1("FRM_ERR
    ");
            WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
        }else if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)){//FIFO满中断
            fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;//读出来内部FIFO缓存的数据个数
            while (fifo_len--){
                if(Uart0ReadCnt<Uart0ReadBuffLen-1){//别超过了数组的大小
                    Uart0ReadBuff[Uart0ReadCnt] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;//取出来一个数据
                    Uart0ReadCnt++;
                }
                else{
                    Uart0ReadCnt = 0;
                }
            }
            WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
    
        }else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)){//FIFO空闲中断
            fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;//读出来内部FIFO缓存的数据个数
            while (fifo_len--){
                if(Uart0ReadCnt<Uart0ReadBuffLen-1){//别超过了数组的大小
                    Uart0ReadBuff[Uart0ReadCnt] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;//取出来一个数据
                    Uart0ReadCnt++;
                }
                else{
                    Uart0ReadCnt = 0;
                }
            }
    
            BufferManageWrite(&buff_manage,Uart0ReadBuff,Uart0ReadCnt,&WriteState);//把数据插入缓存
            Uart0ReadCnt=0;
            WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
        }else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)){
            DBG("e");
        CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
        #if UART_BUFF_EN
            tx_start_uart_buffer(UART0);
        #endif
            //system_os_post(uart_recvTaskPrio, 1, 0);
            WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
            
        }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);
            DBG1("RX OVF!!
    ");
        }
    }

    4.3提取缓存数据,并输出

    BufferManageRead(&buff_manage,UartReadbuffCopy,&buff_manage.ReadLen);/*取出缓存的数据*/
        if(buff_manage.ReadLen>0){/*缓存取出来数据*/
            uart0_tx_buffer(UartReadbuffCopy,buff_manage.ReadLen);
        }

    测试

    如果想应用到自己的项目,拷贝以下文件

    RTOS

    RTOS

    RTOS

    1.默认所有的数据都使用串口0输出

    官方提供了函数可以选择printf利用哪一个串口输出

    配置printf使用串口1打印输出,波特率115200

    (注:这样配置对于调试程序很有帮助,printf当做程序运行的日志打印)

      

      

      

    void
    uart_init_new(void)
    {
        UART_WaitTxFifoEmpty(UART0);
        UART_WaitTxFifoEmpty(UART1);
    
        UART_ConfigTypeDef uart_config;
        uart_config.baud_rate    = BIT_RATE_115200;//波特率
        uart_config.data_bits     = UART_WordLength_8b;//数据位数
        uart_config.parity          = USART_Parity_None;//奇偶校验
        uart_config.stop_bits     = USART_StopBits_1;//停止位
        uart_config.flow_ctrl      = USART_HardwareFlowControl_None;//硬件流控制
        uart_config.UART_RxFlowThresh = 120;
        uart_config.UART_InverseMask = UART_None_Inverse;
        UART_ParamConfig(UART0, &uart_config);
    
        UART_ParamConfig(UART1, &uart_config);//串口1和串口0的配置一样
    
        UART_IntrConfTypeDef uart_intr;
        //配置启用哪些些中断                                                    数据接收超时                                                               接收数据错误                                                  缓存满中断                                                            发送空中断
        uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
        uart_intr.UART_RX_FifoFullIntrThresh = 10;//接收数据个数超过10个字节进入FIFO满中断
        uart_intr.UART_RX_TimeOutIntrThresh = 2;//超过两个字节的数据的时间没有接收到数据,进入接收超时中断
        uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
        UART_IntrConfig(UART0, &uart_intr);
    
    //    UART_SetPrintPort(UART0);
        UART_SetPrintPort(UART1);//printf使用串口1输出
        UART_intr_handler_register(uart0_rx_intr_handler, NULL);
        ETS_UART_INTR_ENABLE();
    
        /*
        UART_SetWordLength(UART0,UART_WordLength_8b);
        UART_SetStopBits(UART0,USART_StopBits_1);
        UART_SetParity(UART0,USART_Parity_None);
        UART_SetBaudrate(UART0,74880);
        UART_SetFlowCtrl(UART0,USART_HardwareFlowControl_None,0);
        */
    
    }

    串口接收数据说明

    1.该模块默认内部有个128字节的缓存区,默认接收的数据存入缓存区里面

    在中断接收函数里面,从缓存里面获取数据

      

    2.咱们在串口中断函数里面,是在满中断和接收超时中断里面获取串口接收的数据

      

    串口接收数据典型程序

    1.具体请参考: https://www.cnblogs.com/yangfengwu/p/11669373.html

    2.uart.c

    //串口数据接收处理方式:https://www.cnblogs.com/yangfengwu/p/11669373.html
    char Usart0ReadBuff[Usart0ReadLen]={0};//接收数据缓存
    u32  Usart0ReadCnt = 0;//串口接收的数据个数
    u32  Usart0ReadCntCopy = 0;//用于拷贝串口接收的数据个数
    u32  Usart0IdleCnt = 0;//空闲时间累加变量

     

    LOCAL void
    uart0_rx_intr_handler(void *para)
    {
        uint8 RcvChar;
        uint8 uart_no = UART0;//UartDev.buff_uart_no;
        uint8 fifo_len = 0;
        uint8 buf_idx = 0;
    //    uint8 fifo_tmp[128] = {0};
        uint32 uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
        while (uart_intr_status != 0x0) {
            if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)) {//数据错误
                //printf("FRM_ERR
    ");
                WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
            } else if (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST)) {//FIFO满中断
    //            printf("full
    ");
                fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;//读取缓存了多少字节
                buf_idx = 0;
                while (buf_idx < fifo_len) {
                    if(Usart0ReadCnt>Usart0ReadLen){//预防数组溢出
                        Usart0ReadCnt=0;
                    }
                    Usart0ReadBuff[Usart0ReadCnt] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;//把数据存入数组
                    Usart0ReadCnt++;
                    Usart0IdleCnt=0;
    //                uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);//从FIFO读取一字节数据并发送出去
                    buf_idx++;
                }
                WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
            } else if (UART_RXFIFO_TOUT_INT_ST == (uart_intr_status & UART_RXFIFO_TOUT_INT_ST)) {//接收超时中断
    //            printf("tout
    ");
                fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;//读取缓存了多少字节
                buf_idx = 0;
                while (buf_idx < fifo_len) {
                    if(Usart0ReadCnt>Usart0ReadLen){//预防数组溢出
                        Usart0ReadCnt=0;
                    }
                    Usart0ReadBuff[Usart0ReadCnt] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;//把数据存入数组
                    Usart0ReadCnt++;
                    Usart0IdleCnt=0;
    //                uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);//从FIFO读取一字节数据并发送出去
                    buf_idx++;
                }
    
                WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
            } else if (UART_TXFIFO_EMPTY_INT_ST == (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST)) {//发送缓存为空
    //            printf("empty
    
    ");
                WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
                CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
            } else {
                //skip
            }
            uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
        }
    }

     

    3.uart.h

     

    #define Usart0ReadLen 1024  //串口缓存的最大字节数
    #define Usart0IdleTime 10//设置串口空闲时间

    4.user_main.h

    #include "uart.h"
    
    
    extern char Usart0ReadBuff[Usart0ReadLen];//接收数据缓存
    extern u32  Usart0ReadCnt;//串口接收的数据个数
    extern u32  Usart0ReadCntCopy;//用于拷贝串口接收的数据个数
    extern u32  Usart0IdleCnt;//空闲时间累加变量

     

    /**
    * @brief   硬件定时器中断回调函数
    * @param   None
    * @param   None
    * @param   None
    * @param   None
    * @retval  None
    * @warning None
    * @example
    **/
    void hw_test_timer_cb(void)
    {
        if(Usart0ReadCnt!=0){//串口接收到数据
            Usart0IdleCnt++;//空闲时间累加
            if(Usart0IdleCnt>Usart0IdleTime){//累加到期望值(10ms)
                Usart0IdleCnt=0;
                Usart0ReadCntCopy = Usart0ReadCnt;//拷贝接收的数据个数
                Usart0ReadCnt=0;
                /*处理数据
                 * 数据缓存数组:Usart0ReadBuff
                 * 数据长度:Usart0ReadCntCopy
                 * */
            }
        }
    }
    /******************************************************************************
     * FunctionName : user_init
     * Description  : entry of user application, init user function here
     * Parameters   : none
     * Returns      : none
    *******************************************************************************/
    void user_init(void)
    {
        uart_init_new();
    
        printf("SDK version:%s
    ", system_get_sdk_version());
        printf("Ai-Thinker Technology Co. Ltd.
    %s %s
    ", __DATE__, __TIME__);
    
        //定时器初始化
        hw_timer_init(1);//1:循环
        //设置定时器回调函数
        hw_timer_set_func(hw_test_timer_cb);//hw_test_timer_cb:硬件定时器中断回调函数
        hw_timer_arm(1000);//1000:1000us定时进入中断函数
    }

    串口发送

    1.说明

    串口发送实际上是把要发送的数据拷贝到128字节的数据发送缓存区

    然后由模块内部发送

    2.发送函数

    3.为了可以在别的文件中使用,去掉函数前面的LOCAL 标识

     

    测试串口返回接收到的信息

     

    /**
    * @brief   硬件定时器中断回调函数
    * @param   None
    * @param   None
    * @param   None
    * @param   None
    * @retval  None
    * @warning None
    * @example
    **/
    void hw_test_timer_cb(void)
    {
        if(Usart0ReadCnt!=0){//串口接收到数据
            Usart0IdleCnt++;//空闲时间累加
            if(Usart0IdleCnt>Usart0IdleTime){//累加到期望值(10ms)
                Usart0IdleCnt=0;
                Usart0ReadCntCopy = Usart0ReadCnt;//拷贝接收的数据个数
                Usart0ReadCnt=0;
                /*处理数据
                 * 数据缓存数组:Usart0ReadBuff
                 * 数据长度:Usart0ReadCntCopy
                 * */
                for(i=0;i<Usart0ReadCntCopy;i++){
                    uart_tx_one_char(UART0,Usart0ReadBuff[i]);
                }
            }
        }
    }

    NONOS_SDK版本区别

    NONOS提供了使用内部Task接收数据

    如果不想使用Task,想用上面的方式实现

    在最后有一个 uart_init_2 可使用这个函数初始化串口

    void ICACHE_FLASH_ATTR
    uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br)
    {
        // rom use 74880 baut_rate, here reinitialize
        UartDev.baut_rate = uart0_br;
    //    UartDev.exist_parity = STICK_PARITY_EN;
        UartDev.parity = NONE_BITS;
        UartDev.stop_bits = ONE_STOP_BIT;
        UartDev.data_bits = EIGHT_BITS;
        
        uart_config(UART0);
        UartDev.baut_rate = uart1_br;
        uart_config(UART1);
        ETS_UART_INTR_ENABLE();
    
        // install uart1 putc callback
        os_install_putc1((void *)uart1_write_char);//print output at UART1
    
    }
    os_install_putc1((void *)uart0_write_char);//print output at UART0




  • 相关阅读:
    LeetCode 227. Basic Calculator II
    LeetCode 224. Basic Calculator
    LeetCode 103. Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 169. Majority Element
    LeetCode 145. Binary Tree Postorder Traversal
    LeetCode 94. Binary Tree Inorder Traversal
    LeetCode 144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/12375342.html
Copyright © 2011-2022 走看看