【问题标题】:xQueue ESP32 can't send two commandxQueue ESP32 无法发送两个命令
【发布时间】:2021-06-22 03:48:13
【问题描述】:

我正在寻求帮助,因为我被这个问题困扰了很长时间。 我在家里有一个 ESP32 wrover 套件,我已通过 uart 将其连接到 Zigbee 网关模块。我想通过 uart 向模块发送一些命令,因为我将命令放在 xQueue 中,然后我进入一个线程发送到 uart。在另一个线程中,我通过 uart 得到了答案。第一条消息一切顺利,然后在阅读第二条消息时我崩溃了。我认为这是因为我的 tx_msg 不再存在于内存中,但我无法解决问题。而且我认为还有一个同步问题。我受到这个例子的启发,但它不起作用https://www.freertos.org/a00118.html

这是我的代码,如果你知道我需要修改什么或者你能解释我如何修复它,谢谢!

代码编辑:

#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <esp_system.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
//#include <driver/gpio.h>
#include <driver/uart.h>
#include <pthread.h>

typedef unsigned char byte;

// Setup UART buffered IO with event queue
const int uart_buffer_size = 1024;
// Queue used to send and receive complete struct message structures. 
QueueHandle_t uart_queue = NULL;
const int uart_num = UART_NUM_2;

struct message{
    char cmd[128];
    int len;
}tx_msg;

pthread_t zigbee_thread_id;
pthread_t zigbee_send_thread_id;
pthread_t zigbee_receive_thread_id;

/**
 * @brief Configuraiton of UART and set pin that uart use.
 * 
 * @return [int] 0 if is successed
 */
int uart_setup()
{
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    // Configure UART parameters
    ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 18, 19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
    // Install UART driver using an event queue here
    ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, \
                                        uart_buffer_size, 10, &uart_queue, 0));
    return 0;
}

void translate_hexa_to_string(char* data,int len){

    for (int i=0; i<len;i++)
    {
        if (data[i]==2)
            {
                i++;
                data[i]^=0x10;
                printf("%02x ",data[i]);
                    
            }else if (data[i]==3)
            {
                printf("%02x \n",data[i]);
            }else{
                printf("%02x ",data[i]);
            }
            
        }
        printf("\n");
}

/**
 * @brief [Thread]Send commande to Zigbee module by UART
 * 
 */
void * send_cmd(void * arg){
    struct message rx_msg;
    int err;
    while(1){
        if (xQueueReceive(uart_queue, &rx_msg, portMAX_DELAY) == pdPASS){
            printf("len : %d\n",rx_msg.len);
            for(int i=0;i<rx_msg.len;i++){
                printf("%02x \n",rx_msg.cmd[i]);
            }
            printf("\n");
            err = uart_write_bytes(uart_num, (const char *)rx_msg.cmd, rx_msg.len); // Write data to UART.
            if(err != rx_msg.len){
                printf("Err, not all bytes send : %d/%d\n",err,rx_msg.len);
            }
            vTaskDelay(1000 / portTICK_RATE_MS);
        }
    }
    return NULL;
}

/**
 * @brief [Thread]Read response from UART
 * 
 */
void * read_cmd(void * arg){
    char data[512];
    int length = 0;
    while(1){
        if(uxQueueMessagesWaiting(uart_queue) >= 1){
            ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
            length = uart_read_bytes(uart_num, (uint8_t*)data, length, 100);
            if (length > 0){
                printf("[R] len : %d\n",length);
                translate_hexa_to_string(data,length);
                printf("%c",data[6]);
                if(strcmp(data[6],"00")!=0){
                    printf("[R] Command failed\n");
                }
            }
            ESP_ERROR_CHECK(uart_flush(uart_num));
        }
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
    return NULL;
}

/**
 * @brief Configuration of Zigbee module (channel,type) and start network
 * 
 */
void zigbee_config(){
    struct message *ptx_msg;
    //Set Channel
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x21, 0x02, 0x10, 0x02, 0x14, 0x2D, 0x02, 0x10, 0x02, 0x10, 0x02, 0x18, 0x02, 0x10, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    ptx_msg = &tx_msg;
    xQueueSend(uart_queue, (void*)ptx_msg, portMAX_DELAY);
    printf("[S] Set channel to 11\n");
    vTaskDelay(100 / portTICK_RATE_MS);/*
    //Set Type
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x23, 0x02, 0x10, 0x02, 0x11, 0x22, 0x02, 0x10, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    xQueueSend(uart_queue, (void*)&tx_msg, portMAX_DELAY);
    printf("[S] Set as Coordinator\n");
    vTaskDelay(100 / portTICK_RATE_MS);
    //Start Network
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x24, 0x02, 0x10, 0x02, 0x10, 0x24, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    xQueueSend(uart_queue, (void*)&tx_msg, portMAX_DELAY);
    printf("[S] Start Network\n");*/
}

void * ZIGBEE_thread(void * arg){

    /* Create the queue used to send complete struct message structures. */
    uart_queue = xQueueCreate(20, sizeof(struct message));
    if (uart_setup() == -1){
        printf("Err during uart setup\n");
    }
    zigbee_config();
    while(1){
        vTaskDelay(100000 / portTICK_RATE_MS);
    }
    return 0;
    
}

int app_main() {
    
    err += pthread_create(&zigbee_thread_id, NULL, &ZIGBEE_thread, NULL);
    err += pthread_create(&zigbee_send_thread_id, NULL, &send_cmd, NULL);
    err += pthread_create(&zigbee_receive_thread_id, NULL, &read_cmd, NULL);
    // Check if thread is created sucessfuly
    if (err > 0)
    {
        printf("Thread creation failed : %s \n",strerror(err));
        return err;
    }
    pthread_join(zigbee_thread_id, NULL);
    pthread_join(zigbee_send_thread_id, NULL);
    pthread_join(zigbee_receive_thread_id, NULL);
    return 0;
    
}




结果: [S] 设置频道为 11 H H 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] 设置为协调员 [S] 启动网络 H H Guru Meditation 错误:Core 0 恐慌(LoadProhibited)。异常未处理。

核心 0 寄存器转储: PC : 0x400014fd PS : 0x00060130 A0 : 0x800d34d1 A1 : 0x3ffba280
A2:0x00000000 A3:0xfffffffc A4:0x000000ff A5:0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffba230
A10:0x0000000a A11:0x3ffae920 A12:0x00000013 A13:0x00000013 A14:0x00000000 A15:0x00000013 SAR:0x00000000 EXCCAUSE:0x0000001c EXCVADDR:0x00000000 LBEG:0x400014fd LEND:0x4000150d LCOUNT:0xffffffff

回溯:0x400014fa:0x3ffba280 0x400d34ce:0x3ffba290 0x400d1bad:0x3ffba2c0 0x40085339:0x3ffba2e0 0x400d34ce:C:\Users\tgasser\Documents\ESP32\template-app\fibonacci-app\build/../main/main.c:97 的 send_cmd

0x400d1bad:pthread_task_func 在 C:/Users/tgasser/esp/esp-idf/components/pthread/pthread.c:209(鉴别器 15)

0x40085339:vPortTaskWrapper 位于 C:/Users/tgasser/esp/esp-idf/components/freertos/xtensa/port.c:143

【问题讨论】:

    标签: queue pthreads esp32 freertos


    【解决方案1】:

    您误解了队列的接口。 xQueueReceive 希望您提供实际内存来存储其有效负载。在函数send_cmd 中,您将一个指向另一个未初始化指针的指针传递给xQueueReceive

        struct message *rx_msg;
    ...
            if (xQueueReceive( uart_queue, &rx_msg, portMAX_DELAY) == pdPASS && uart_queue != NULL){
    ...
    

    相反,您需要创建一个预期类型的​​变量并将指针传递给该变量。

        struct message rx_msg;
    ...
            if (xQueueReceive( uart_queue, &rx_msg, portMAX_DELAY) == pdPASS && uart_queue != NULL){
    ...
    

    同样发布到队列不正确。你给它一个指向tx_msg的指针,但它只需要指向tx_msg的指针。

    错误:

    xQueueSend(uart_queue, (void*)&ptx_msg, portMAX_DELAY);
    

    对:

    xQueueSend(uart_queue, (void*)ptx_msg, portMAX_DELAY);
    

    作为关于 FreeRTOS 的优秀资源,我在他们的网站上推荐这本书/教程:Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide

    附注:请将控制台输出作为文本发布,而不是屏幕截图。

    【讨论】:

    • 感谢您的回答!我会阅读文件!但是,如果我输入 struct message rx_msg 而不是 ``struct message *rx_msg``` 我会返回我认为是地址而不是值:使用指针:[S] 将通道设置为 11 hh 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] 设置为协调器 [S] 启动网络 hh 无指针 : [S] 将通道设置为 11 hh 18 26 fb 3f [S] 设置为协调器 [S] 启动网络hh 18 26 fb 3f hh 18 26 fb 3f
    • 对,那是因为使用xQueueSend 发布到队列也是不正确的。我也更新了我的答案来解决这个问题。
    • 哦,谢谢,但我现在什么也没收到 TT len : 19 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] 将频道设置为 11 len : 0跨度>
    • 请使用您现在拥有的代码更新您的帖子。
    • 我刚刚编辑了它!提前感谢您的帮助!
    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    相关资源
    最近更新 更多