簡體   English   中英

STM32 UART中斷溢出后不起作用

[英]STM32 UART Interrupt does not work after overflow

我目前正在使用帶有 STM32F103C8 微控制器的 SIM800C 模塊。 由於SIM800C是使用AT命令配置的,所以我使用UART進行通信。 目前,我在中斷模式下將 USART3 配置為 9600 波特(我嘗試使用簡單接收,但它只接收到第一個字符。我認為這是因為答案太快或 smth)。 所以,這是我發送 AT 命令的代碼:

static void send_at(char *at_cmd, char *reply, uint16_t timeout)
{

    offset = strlen(at_cmd) + 1; // offset of reply of SIM800
    len = strlen(reply) + 2 + offset; // overall reply length

    rx_buffer = (char *) calloc(len, sizeof(char));
    expected_ans = (char *) calloc(len, sizeof(char));

    sprintf(expected_ans, "%s\r\n", reply);

    HAL_UART_Receive_IT(sim_uart, (uint8_t *) rx_buffer, len); // \r\r\n
    HAL_Delay(10);
    HAL_UART_Transmit(sim_uart, (uint8_t *) at_cmd, strlen(at_cmd), timeout);
}

對於"AT\r\n"命令,SIM800 返回"AT\r\nOK\r\n" ,因此,offset 是僅回復開始的指針(在本例中為 4,跳過"AT\r\n"部分) . 所以,當我收到答案時,我在回調函數中檢查它:


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart)
{
    rx_buffer[len] = 0; // truncate garbage data

    if (!strcmp(rx_buffer + offset, expected_ans))
        ++state;
    else
        state = 0;
}

state是可變的,它表示要發送哪條 AT 命令(顯然,當 state 增加時,將執行下一條 AT 命令)。 一切正常,但是......如果回復溢出,一切都結束了。

例如,對於啟用 GPRS 的 AT 命令"AT+SAPBR=1,1\r\n" ,可以有一個答案"ERROR"而不是"OK" 因為,在"ER"中斷觸發后,我已經調用了長度為"OK"的 RX 中斷。 然而,對於此后的所有其他中斷調用,中斷不會觸發,即使答案是"OK" 基本上,回復"ERROR"溢出並且下一個中斷被禁用。 我不知道是什么問題以及為什么會發生這種情況。 有沒有辦法事先知道傳入數據的大小或在回調函數中刷新緩沖區?

這是我的主要功能:

void sim800_init(UART_HandleTypeDef *uart)
{
    sim_uart = uart;

    while(state < 8)
    {
        switch (state)
        {
            case 0:
                send_at(AT, "OK", 1000);
                break;
            case 1:
                send_at(AT_SAPBR_CONTYPE, "OK", 5000);
                break;
            case 2:
                send_at(AT_SAPBR_SET_APN, "OK", 5000);
                break;
            case 3:
                send_at(AT_ENABLE_GPRS, "OK", 5000);
                break;
            case 4:
                send_at(AT_HTTP_INIT, "OK", 10000);
                break;
            case 5:
                send_at(AT_HTTPPARA_CID, "OK", 10000);
                break;
            case 6:
                send_at(AT_HTTPPARA_URL, "OK", 5000);
                break;
            case 7:
                send_at(AT_HTTPPARA_CONTENT, "OK", 5000);
                break;
        }

        HAL_Delay(1000);
    }
}

簡單的答案:使用循環緩沖區並一次接收一個字符。 您可以在中斷中重新加載接收,但它並不是很干凈。 中斷更新循環緩沖區頭指針。 主要代碼只是讀取頭指針並使用/更新尾指針來進行解析。 只需解析您的循環緩沖區並搜索“/r/n”(如果它存在)就在那里拆分,如果需要則解析和交換狀態。 請記住,接收應該是連續的,不僅在您期望數據到來時。 您遲早也需要處理未經請求的消息。 還要記住在中斷和主循環上寫入/讀取的變量上使用編譯器屏障或至少使用“易失性屬性”。

長答案提示:在循環模式下使用 dma,idle halffull 和 full dma 中斷將幫助您在主循環中觸發解析。

對於你的問題:

有沒有辦法事先知道傳入數據的大小或在回調函數中刷新緩沖區?

你不能。 UARTS 有 1 字節的硬件緩沖區。 如果你在沒有讀取的情況下將其填滿,它將在下一個字節接收時觸發溢出錯誤,並且整個讀取過程將掛起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM