ESP 8266-FReeRTOS-シリアルポート割り込み(一)

11845 ワード

まず楽鑫官方の参考文献には簡単な言葉しかありません.
シリアル中断に関する公式リファレンスドキュメントの説明
 ESP8266_RTOS_SDKのデフォルトでは、UART 0を使用してデバッグ情報を印刷します.デフォルトのボーレートは74880です.ユーザーはuser_Init中⾃定義初期化UART,参照uart_init_new実現.UART駆動例:ESP 8266_RTOS_SDK\driver_lib\driver\uart.c UART 0の初期化を例に挙げます.UARTパラメータの定義:
UART_ConfigTypeDef  uart_config;

uart_config.baud_rate   =   BIT_RATE_74880;

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割込み処理関数を登録し、UART割込みを可能にする:
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;

uart_intr.UART_RX_TimeOutIntrThresh = 2;

uart_intr.UART_TX_FifoEmptyIntrThresh = 20;

UART_IntrConfig(UART0, &uart_intr);

UART_SetPrintPort(UART0);

UART_intr_handler_register(uart0_rx_intr_handler);

ETS_UART_INTR_ENABLE();

そしてこれ以上説明はありません!
このブログから見ると、http://blog.sina.com.cn/s/blog_ed2c83c30102xc0o.html
  • シリアルポートは常にランダムにデータを送信し、データサイズが未知である.
  • 受信したデータをどのように格納するか.
  • は、完全なデータが送信されたことをどのように決定するか.

  • 上記の3つの要求を達成するには、その構想は大体以下の通りである.
  • ランダムデータの受信は、割り込みにより実現され、割り込み構造体にUART_が設定されるRXFIFO_FULL_INT_ENAとUART_RXFIFO_TOUT_INT_ENA、それに基づいて該当するゲート値を設定します.
  • UART_IntrConfTypeDef uart_intr;
    uart_intr.UART_IntrEnMask = UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA;
    uart_intr.UART_RX_FifoFullIntrThresh = 63;
    uart_intr.UART_RX_TimeOutIntrThresh = 20;
    uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
    UART_IntrConfig(UART0, &uart_intr);
  • 一度に63バイト(実際のテストは64バイトのようです)を受信するとUART_が生成されますRXFIFO_FULL_INT_ST割り込み.
  • 受信データが63バイト未満で、所定時間にデータを受信していない場合、UART_が生成されるRXFIFO_TOUT_INT_ST割り込み.(esp 8266は、割り込み関数を自分で実現する必要はなく、割り込みコールバック関数を登録することによって実現する)
  • .
  • 受信データが比較的速いので、先にキャッシュしてから処理します.私はここで循環キューを採用してキャッシュを実現します.最初は、私は文字ごとにキューに格納していましたが、端末コールバック関数の送信データが速く、文字ごとの格納処理が遅すぎて、memcpy()関数でキューに格納しました.(ここでは、次のデータが送信される前に前のデータがタスク処理で完了したことを確認するために合理的に推定することに注意)
  • は、格納されたデータに対して、タイミングタスクを設計し、キューに検索関数を設計し、キュー内のデータを一定時間おきにクエリーし、最後の「」文字列を検索し、このデータ長を返し、jsonデータにカプセル化して送信する.ここでは,ループキューを用いて,重複送信を回避し,データを消去することなく,既存のデータを直接上書きすることができる.キュー構造体は、typedef struct{u 8*p_o;u 8*volatile p_r;u 8*volatile p_w;volatile u 32 fill_cnt;u 32 size;}RINGBUF;

  • 最終的にやった!!
    まず割り込みサービス関数を登録し、登録が完了するとすぐにキューを初期化し(タスク間でデータを転送しやすい)、シリアルポートタスクを開始します.割り込みサービス関数を作成し、割り込みサービス関数で条件を判断します.シリアル・ポート・データがオーバーフローした場合にキューにデータを送信するように設定できます.シリアル・ポート・タスクでは、キューにデータが送信されていることを検出すると、すぐにシリアル・ポートで印刷されます.
    user_main.c(不要なコードをいくつか削除しました)
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "freertos/queue.h"
    #include "esp_common.h"
    #include "esp_wifi.h"
    #include "uart.h"
    #include "apps/sntp.h"
    
    #include "iot_export.h"
    #include "aliyun_port.h"
    #include "aliyun_config.h"
    #include "ota.h"
    #include "mqtt.h"
    
    int got_ip_flag = 0;
    ota_info_t *p_ota_info = NULL;
    
    enum {
        UART_EVENT_RX_CHAR,
        UART_EVENT_MAX
    };
    
    typedef struct _os_event_ {
        uint32 event;
        uint32 param;
    } os_event_t;
    
    
    xTaskHandle xUartTaskHandle;
    xQueueHandle xQueueUart;
    
    LOCAL STATUS
    uart_tx_one_char(uint8 uart, uint8 TxChar)
    {
        while (true) {
            uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
    
            if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
                break;
            }
        }
    
        WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
        return OK;
    }
    
    
    //           :3
    LOCAL void
    user_uart_task(void *pvParameters)
    {
        os_event_t e;
    
        for (;;) {
            if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY)) {
                switch (e.event) {
                    case UART_EVENT_RX_CHAR:
                        printf("%c", e.param); //       
                        break;
    
                    default:
                        break;
                }
            }
        }
    
        vTaskDelete(NULL);
    }
    
    
    
    //            :2
    LOCAL void
    user_uart0_rx_intr_handler(void *para)
    {
        os_event_t e;
        portBASE_TYPE xHigherPriorityTaskWoken;
    
        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\r
    ");
    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)) { // //printf("*************full\r
    ");
    fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; buf_idx = 0; /* while (buf_idx < fifo_len) { uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF); buf_idx++; } */ RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; // WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); // e.event = UART_EVENT_RX_CHAR; e.param = RcvChar; xQueueSendFromISR(xQueueUart, (void *)&e, &xHigherPriorityTaskWoken); // portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ; } } // :1 void user_uart_init(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_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 uart_intr.UART_RX_TimeOutIntrThresh = 10; uart_intr.UART_TX_FifoEmptyIntrThresh = 20; UART_IntrConfig(UART0, &uart_intr); UART_SetPrintPort(UART0); UART_intr_handler_register(user_uart0_rx_intr_handler, NULL); ETS_UART_INTR_ENABLE(); // xQueueUart = xQueueCreate(32, sizeof(os_event_t)); xTaskCreate(user_uart_task, (uint8 const *)"uTask", 512, NULL, 5, &xUartTaskHandle); } void user_init(void) { user_uart_init(); }