×

ESP32------关于UART(串口)的使用(2)

zxjy辉 zxjy辉 发表于2023-07-10 16:53:03 浏览331 评论0

抢沙发发表评论

风景图片 - 堆糖.jpeg

不直接在ISR程序中处理中断,利用分配资源函数,传递一个消息队列,进行保存中断类型,再通过任务进行处理对应的中断


  1. 专用包装中带:封装好的一个中断,利用rtos任务来响应中断

    1. ESP32------关于UART(串口)的使用(1)这篇文章中,通过 uart_driver_install 方法安装一个串口驱动来分配资源,同时也注册了一个中断,其中一个参数就是 消息队列

      图片.png

    2. 通过在任务中接收消息队列,根据消息队列中的值,判断当前串口的中断类型,然后再进行处理;Ps:这个消息队列的值是 uart_event_t类型的

      1. 枚举器UART_DATA
        UART数据事件

      2. 枚举器UART_BREAK
        UART中断事件

      3. 枚举器UART_BUFFER_FULL
        UART RX缓冲区已满事件

      4. 枚举器UART_FIFO_OVF
        UART FIFO溢出事件

      5. 枚举器UART_FRAME_ERR
        UART RX帧错误事件

      6. 枚举器UART_PARITY_ERR
        UART RX奇偶校验事件

      7. 枚举器UART_DATA_BREAK
        UART TX数据和中断事件

      8. 枚举器UART_PATTER_DET
        检测到UART模式

      9. 枚举器UART_EVENT_MAX
        UART事件最大索引

  2. 参考代码

    1. /// @brief 串口2的事件检测
      /// @param param 
      void Uart2_Test_Task( void *param )
      {
          uart_event_t my_event;
          char buffer[128];
           char* test_str = "This is a uart2 data \n";
           char* test_str1 = "This is uart2 break \n";
           char* buffer_full = "buffer is full \n";
          while (1)
          {
              if (xQueueReceive(uart2_queue,&my_event,10))
              {
                  switch (my_event.type)
                  {
                  /*================================================================================
                   数据事件:最好要快速处理,因为数据事件比其他类型多得多,不及时就会导致,队列满了,错过其他
                   事件
                  ================================================================================*/
                  case UART_DATA:                                //接收到数据,或则说是串口有数据传输?
                      uart_write_bytes(UART_NUM_2, (const char*)test_str,22);
                      break;
                  /*================================================================================
                   中断事件:没搞懂!!
                  ================================================================================*/
                  case UART_BREAK:    
                      uart_write_bytes(UART_NUM_2, (const char*)test_str1,strlen(test_str1));       
                      break;
                   /*================================================================================
                   接收缓冲区溢出:如果缓冲区已满,则应考虑增加缓冲区大小
                                 例如,为了读取更多的数据,我们在这里直接刷新rx缓冲区。
                  ================================================================================*/
                  case UART_BUFFER_FULL:
                      uart_write_bytes(UART_NUM_2, (const char*)buffer_full,strlen(buffer_full));  
                      uart_flush_input(UART_NUM_2);
                      xQueueReset(uart2_queue);
                      break;
                   /*================================================================================
                   FIFO溢出:则应考虑流控制,为了读取更多的数据,我们在这里直接刷新rx缓冲区。
                  ================================================================================*/   
                  case UART_FIFO_OVF:
                      uart_flush_input(UART_NUM_2);
                      xQueueReset(uart2_queue);
                      break; 
                  default:
                      break;
                  }
              }
              
              // vTaskDelay(1);
          }
          
      }


    2. 完整代码

      1. #define Uart2_Tx 17
        #define Uart2_Rx 16
        #define Uart2_RTS 7
        #define Uart2_CTS 8
        QueueHandle_t uart2_queue;                          //串口2的消息队列,z这个消息队列是用来存储中断事件类型的
        
        
        /// @brief 串口2的事件检测
        /// @param param 
        void Uart2_Test_Task( void *param )
        {
            uart_event_t my_event;
            char buffer[128];
             char* test_str = "This is a uart2 data \n";
             char* test_str1 = "This is uart2 break \n";
             char* buffer_full = "buffer is full \n";
            while (1)
            {
                if (xQueueReceive(uart2_queue,&my_event,10))
                {
                    switch (my_event.type)
                    {
                    /*================================================================================
                     数据事件:最好要快速处理,因为数据事件比其他类型多得多,不及时就会导致,队列满了,错过其他
                     事件
                    ================================================================================*/
                    case UART_DATA:                                //接收到数据,或则说是串口有数据传输?
                        uart_write_bytes(UART_NUM_2, (const char*)test_str,22);
                        break;
                    /*================================================================================
                     中断事件:没搞懂!!
                    ================================================================================*/
                    case UART_BREAK:    
                        uart_write_bytes(UART_NUM_2, (const char*)test_str1,strlen(test_str1));       
                        break;
                     /*================================================================================
                     接收缓冲区溢出:如果缓冲区已满,则应考虑增加缓冲区大小
                                   例如,为了读取更多的数据,我们在这里直接刷新rx缓冲区。
                    ================================================================================*/
                    case UART_BUFFER_FULL:
                        uart_write_bytes(UART_NUM_2, (const char*)buffer_full,strlen(buffer_full));  
                        uart_flush_input(UART_NUM_2);
                        xQueueReset(uart2_queue);
                        break;
                     /*================================================================================
                     FIFO溢出:则应考虑流控制,为了读取更多的数据,我们在这里直接刷新rx缓冲区。
                    ================================================================================*/   
                    case UART_FIFO_OVF:
                        uart_flush_input(UART_NUM_2);
                        xQueueReset(uart2_queue);
                        break; 
                    default:
                        break;
                    }
                }
                
                // vTaskDelay(1);
            }
            
        }
        
        
        /// @brief 串口2的参数配置以及资源分配
        /// @param 无
        void Uart2_Study_Init( void )
        {
            uart_config_t my_uart={
                .baud_rate = 115200,                        //波特率
                .data_bits = UART_DATA_8_BITS,              //数据位
                .stop_bits = UART_STOP_BITS_1,              //停止位
                .parity = UART_PARITY_DISABLE,              //奇偶校验位
                .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,      //流控
                .rx_flow_ctrl_thresh = 122,                 //触发流控的阈值
                // .source_clk = UART_SCLK_DEFAULT,            //设置时钟源
            };  
           
            //uart_config    //设置一个默认的串口,使用串口1
            uart_param_config(UART_NUM_2,&my_uart);
             ///设置了对应的引脚和对应的串口号,因为有可能你并没有使用一些引脚
            uart_set_pin(UART_NUM_2,Uart2_Tx,Uart2_Rx,UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE);  
            
            ///分配了串口的资源 ,在这里就已经注册了一个idf默认自带的一个中断服务程序
            uart_driver_install(UART_NUM_2,1024,1024,10,&uart2_queue,0);
        
            //创建一个任务来处理来自ISR的UART事件
            xTaskCreate(Uart2_Test_Task,"Uart2_Test_Task",1024,NULL,3,NULL);
        }


  3. 其他中断:还没整明白


    图片.png

#好好学习!

群贤毕至

访客