[ESP][Driver] ESP series wildfire PID debugging assistant protocol driver adaptation

1 Introduction

Wildfire PID debugging assistant driver, suitable for ESP series, developed based on ESP-IDF5.0
Github: https://github.com/taxue-alfred/firetool_PID_driver_esp
Gitee: https://gitee.com/TaXue_TianXing/firetool_PID_driver_esp

2. Answer questions

Is ESP-IDF4.4 available? Available in theory, but not tested

firetool_PID_adaptorFound under CMakeLists.txt, the 5.0 version removes the default import of the driver, and the 4.4 version imports by default driver. The 4.4 version is theoretically available, but it has not been tested.

image-20230115143538947

3. Directory structure

The project is written with a two-layer structure, the bottom layer and the high layer. The bottom layer is responsible for serial port initialization and data transmission, and the high layer is responsible for data processing and function implementation.

This project is written using object-oriented thinking and supports multiple serial ports to create multiple instances, but it is not recommended to use it. It is recommended to send multiple sets of data through the "channel" function of the wildfire PID debugging assistant

├─components
│  ├─firetool_PID_adaptor
│  │  │  adaptor_low_layer.c 库底层
│  │  │  CMakeLists.txt
│  │  │  firetool_PID_adaptor.c 库高层
│  │  │
│  │  └─includes
│  │          adaptor_low_layer.h
│  │          firetool_PID_adaptor.h
│  │
│  └─TransferLib
│      │  CMakeLists.txt
│      │  TransferLib.c 负责数据格式转换
│      │
│      └─includes
│              TransferLib.h
└─main
        CMakeLists.txt
        firetool_PID_driver_esp.c 示例应用

4. How to transplant

Just transplant this library and modify the bottom layer.

1. Modify the structure

The modified content is under adapter_low_layer.h

The source code of this library is as follows:

/**调用初始化函数之前必须先调用设置回调函数函数!!!!!!**/

//定义串口类
typedef struct{
    
    
    uart_config_t uart_config;
    int uart_num;
}AdaptorUart;

uart_config_tIt is the serial port configuration structure, uart_numwhich is the serial port device in the MCU. For example, if the second serial port device is used, it should be au_init_uartpassed in in IDF UART_NUM_2, and then assigned to . The content in uart_numthe port needs to be modified when transplanting .AdaptorUart

2. Modify au_init_uart()the function

The modified content is under adapter_low_layer.c

uart_config_tThis function is mainly to assign values ​​to and other members in the class structure mentioned above , and then install the serial port (depending on the development method of the MCU)

Part of the source code of this library:

void au_init_uart(AdaptorUart * adaptor_uart, int band_rate, int rx_pin,
                  int tx_pin, int uart_num, int buffer_size)
{
    
    
    //设置串口参数
    adaptor_uart->uart_config.baud_rate = band_rate;
    adaptor_uart->uart_config.data_bits = UART_DATA_8_BITS;
    adaptor_uart->uart_config.parity = UART_PARITY_DISABLE;
    adaptor_uart->uart_config.stop_bits = UART_STOP_BITS_1;
    adaptor_uart->uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
    adaptor_uart->uart_config.source_clk = UART_SCLK_DEFAULT;

    //存储必要值
    adaptor_uart->uart_num = uart_num;

    //set uart param
    ESP_ERROR_CHECK(uart_param_config(uart_num, &adaptor_uart->uart_config));

    //set uart pins
    ESP_ERROR_CHECK(uart_set_pin(uart_num, tx_pin, rx_pin,
                                 UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE));

    //driver install
    ESP_ERROR_CHECK(uart_driver_install(uart_num, buffer_size,
                                        buffer_size, 20,
                                        &uart1_queue,0));
}

3. Modify the sending and receiving functions

The modified content is under adapter_low_layer.c

au_init_uart()After the relevant parts are initialized, you can directly write the sending and receiving logic here.

Source code of this library:

/**
 * @brief 发送字节函数
 * @param adaptor_uart 串口类
 * @param contents 发送内容
 * @param len 发送的字节个数
 * @return 发送的字节个数
 */
int au_uart_send_bytes(AdaptorUart * adaptor_uart, char * contents, int len)
{
    
    
    return uart_write_bytes(adaptor_uart->uart_num, contents, len);
}

/**
 * @brief 接收字节函数
 * @param adaptor_uart 串口类
 * @param data 存放接收内容的内存空间
 * @param max_len 存放接收内容的内存空间大小
 * @return 本次接收的字节个数,如果缓存已有的数据大于max_len,则只返回max_len大小的数据,
 * 反之则返回缓冲区的全部数据
 */
int au_uart_read_bytes(AdaptorUart * adaptor_uart, char * data, int max_len)
{
    
    
    int rev_data_len = 0;
    //检查接收缓冲区中是否有数据
    ESP_ERROR_CHECK(uart_get_buffered_data_len(adaptor_uart->uart_num, (size_t*)&rev_data_len));
    if(rev_data_len != 0){
    
    
        if(rev_data_len <= max_len)
            return uart_read_bytes(adaptor_uart->uart_num, data, rev_data_len,
                                   0);
        else return uart_read_bytes(adaptor_uart->uart_num, data, max_len,
                                    0);
    }
    return 0;
}

4. Modify the interrupt function

The modified content is under adapter_low_layer.c

The purpose of the interrupt function is only one, to call the callback ( ) function after an interrupt occurs received_data_cb().

The implementation of the IDF interrupt function is similar to the polling method, STM32and it is enough to directly call the function in the corresponding interrupt function received_data_cb()to pass in the corresponding data.

IDF event listener function:

/**
 * @brief 事件监听函数,可以理解为中断读取数据
 * @param pvPara
 */
void uart_event_task(void * pvPara)
{
    
    
    uart_event_t event;
    AdaptorUart * adaptorUart_rev = (AdaptorUart * )pvPara;

    while(1){
    
    
        if(xQueueReceive(uart1_queue, &event, portMAX_DELAY)){
    
    
            //UART接收到数据
            if (event.type == UART_DATA){
    
    
                //malloc大小
                uint16_t rev_size = 1024;
                char * received_data = malloc(rev_size * sizeof(char ));
                if (received_data != NULL){
    
    
                    int received_length = 0;
                    received_length = au_uart_read_bytes(adaptorUart_rev,
                                                         received_data, rev_size);
                    //调用用户自定义回调函数,进行数据处理
                    if(received_length != 0)
                    {
    
    
                        received_data_cb(adaptorUart_rev, received_data,
                                         received_length);
                    }

                    free(received_data);
                }else{
    
    
                    assert("malloc the memory failed!\n");
                }
            }
        }
    }
}

5. Protocol Reference

Motor PID Control Supplement - Introduction to Serial Port Protocol of Wildfire Host Computer

Guess you like

Origin blog.csdn.net/qq_38844263/article/details/128694753