[英]xQueue ESP32 can't send two command
我正在尋求幫助,因為我被這個問題困擾了很長時間。 我在家里有一個 ESP32 wrover 套件,我已通過 uart 將其連接到 Zigbee 網關模塊。 我想通過 uart 向模塊發送一些命令,因為我將命令放在 xQueue 中,然后我進入一個線程發送到 uart。 在另一個線程中,我通過 uart 得到了答案。 第一條消息一切順利,然后在閱讀第二條消息時我崩潰了。 我認為這是因為我的 tx_msg 不再存在於 memory 中,但我無法解決問題。 而且我認為還有一個同步問題。 我受到這個例子的啟發,但它不起作用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 hh 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] 設置為協調員 [S] 啟動網絡 hh Guru Meditation Error: Core 0 panic'ed (禁止加載)。 異常未處理。
核心 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
Backtrace:0x400014fa:0x3ffba280 0x400d34ce:0x3ffba290 0x400d1bad:0x3ffba2c0 0x40085339:0x3ffba2e0 0x400d34ce: send_cmd at C:\Users\tgasser\Documents\ESP32\template-app\fibonacci-app\build/../main/main.c:97
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
您誤解了隊列的接口。 xQueueReceive
希望您提供實際的 memory 來存儲其有效負載。 在 function 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 的優秀資源,我推薦他們 web 站點上的書/教程: 掌握 FreeRTOS 實時 Kernel - 動手教程指南。
旁注:請將控制台 output 作為文本發布,而不是屏幕截圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.