ESP32学习

1.基础配置

配置芯片:

  • Serial Flasher config -配置封装外flash
  • ESP PSRAM -配置封装没PSRAM
  • ESP System Setting -ESP32系统配置(主频)
  • FreeRTOS -配置时钟节拍

2.常用函数

函数名功能说明关键参数 / 注意点
gpio_config(&gpio_config_t config)一站式配置 GPIO(模式 / 上下拉 / 中断)结构体参数:

pin_bit_mask:引脚掩码(如1ULL<<GPIO_NUM_2

modeGPIO_MODE_INPUT/OUTPUT

pull_up_enGPIO_PULLUP_ENABLE/DISABLE
gpio_set_level(gpio_num_t pin, uint32_t level)设置 GPIO 输出电平(0/1)无需手动使能时钟,直接调用
gpio_get_level(gpio_num_t pin)读取 GPIO 输入电平
gpio_install_isr_service(0)安装 GPIO 中断服务全局中断初始化,仅需调用一次
gpio_isr_handler_add(pin, isr_handler, arg)绑定 GPIO 中断处理函数中断函数需为void isr_handler(void* arg)
FreeRTOS 任务管理
xTaskCreate(task_func, name, stack_size, arg, prio, handle)创建任务stack_size:ESP32 建议≥2048 字节

prio:优先级(0~31,数值越高优先级越高)
vTaskDelete(TaskHandle_t handle)删除任务NULL表示删除当前任务
xQueueCreate(length, item_size)创建队列(任务间通信)length:队列长度

item_size:单个数据字节数
xQueueSend(queue, &data, timeout)发送数据到队列timeout:超时时间(pdMS_TO_TICKS (100))
xQueueReceive(queue, &data, timeout)从队列接收数据-
xSemaphoreCreateBinary()创建二值信号量-
xSemaphoreGive(sem)释放信号量-
xSemaphoreTake(sem, timeout)获取信号量-
UART 串口函数
uart_param_config(uart_num_t uart, &uart_config_t)配置串口参数结构体参数:

baud_rate:波特率(115200)

data_bitsUART_DATA_8_BITS

parityUART_PARITY_DISABLE
uart_set_pin(uart_num, tx, rx, rts, cts)映射串口引脚ESP32 支持任意 GPIO 映射(如 UART0_TX=GPIO16)
uart_driver_install(uart_num, rx_buf_size, tx_buf_size, 0, NULL, 0)安装串口驱动rx_buf_size:接收缓冲区大小(如 1024)
uart_write_bytes(uart_num, data, len)发送字节数据阻塞式发送
uart_read_bytes(uart_num, buf, len, timeout)读取字节数据timeout:超时时间(pdMS_TO_TICKS (100))
RMT 外设函数
rmt_new_tx_channel(&tx_chan_config, &rmt_chan)创建 RMT TX 通道结构体参数:

gpio_num:输出引脚

resolution_hz:时钟分辨率(如 10MHz)
rmt_new_copy_encoder(&config, &encoder)创建 copy 编码器(ESP-IDF v5.1+)替代弃用的rmt_new_encoder
rmt_transmit(chan, encoder, data, len, &tx_config)发送 RMT 符号数据-
rmt_enable(rmt_chan)启用 RMT 通道-
ADC 模拟采集函数
adc_oneshot_new_unit(&adc_config, &adc_unit)创建 ADC 单元ESP32-C6 仅支持 ADC1(GPIO0~6)
adc_oneshot_config_channel(adc_unit, chan, &config)配置 ADC 通道结构体参数:

atten:衰减系数(如ADC_ATTEN_DB_11,测量 0~3.3V)

bitwidthADC_BITWIDTH_12
adc_oneshot_read(adc_unit, chan, &raw_data)读取 ADC 原始值原始值范围:0~4095(12 位)
Wi-Fi 核心函数
esp_wifi_init(&wifi_init_config_t)初始化 Wi-Fi 驱动-
esp_wifi_set_mode(WIFI_MODE_STA/AP)设置 Wi-Fi 模式(STA/AP)STA:连接路由器;AP:自建热点
esp_wifi_set_config(interface, &wifi_config)设置 Wi-Fi 参数STA 模式:配置 SSID / 密码

wifi_config.sta.ssid:路由器名称

wifi_config.sta.password:密码
esp_wifi_start()启动 Wi-Fi-
esp_wifi_connect()STA 模式连接路由器-

2.模块代码

2.1 WIFi

连wifi四步走

  • 初始化 nvs_flash_init esp_netif_init //初始化nvs和网络接口 esp_event_loop_create_default //创建事件循环 esp_netif_create_default_wifi_sta //创建wifi statin模式
  • 使用esp_event_handler_instance_register注册wifi和ip事件
  • wifi配置与启动 esp_wifi_init
    esp_wifi_set_mode esp_wifi_set_config esp_wifi_start esp_wifi_connect
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <stdio.h>

#include "freertos/FreeRTOS.h"

#include "freertos/task.h"

#include "freertos/event_groups.h"

#include "driver/gpio.h"

#include "esp_log.h"

#include "freertos/queue.h"

#include <string.h>

#include <stdint.h>
  

#include "esp_wifi.h"

#include "esp_event.h"

#include "nvs_flash.h"



// 1. 定义你的 Wi-Fi 信息

#define EXAMPLE_ESP_WIFI_SSID      "esp"

#define EXAMPLE_ESP_WIFI_PASS      "12345678"

  

// 2. 事件处理函数

static void event_handler(void* arg, esp_event_base_t event_base,

                                int32_t event_id, void* event_data)

{

    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {

        esp_wifi_connect(); // 启动后开始连接

    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {

        esp_wifi_connect(); // 断开后尝试重连

        ESP_LOGI("WIFI", "重连中...");

    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {

        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;

        ESP_LOGI("WIFI", "成功获取IP: " IPSTR, IP2STR(&event->ip_info.ip));

        // 这里可以给你的 Task 发送信号,告诉它“可以开始发网络数据了”

    }

}

  

// 3. 封装好的 Wi-Fi 初始化函数

void wifi_init_sta(void)

{

    ESP_ERROR_CHECK(esp_netif_init());

    ESP_ERROR_CHECK(esp_event_loop_create_default());

    esp_netif_create_default_wifi_sta();

  

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

  

    // 注册事件处理

    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL);

    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL);

  

    wifi_config_t wifi_config = {

        .sta = {

            .ssid = EXAMPLE_ESP_WIFI_SSID,

            .password = EXAMPLE_ESP_WIFI_PASS,

        },

    };

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );

    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );

    ESP_ERROR_CHECK(esp_wifi_start() );

}

  

void app_main(void)

{

    // A. 必须初始化 NVS

    esp_err_t ret = nvs_flash_init();

    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {

      ESP_ERROR_CHECK(nvs_flash_erase());

      ret = nvs_flash_init();

    }

    ESP_ERROR_CHECK(ret);

  

    // B. 启动 Wi-Fi

    wifi_init_sta();

}

2.2 lwip TCP

  1. 填写服务器信息
    • struct sockaddr_in 名称;
  2. 创建socket
    • socket( ); 失败时返回 -1
    • 参数:地址(ipv4 ipv6) 套接字类型(SOCK_STREAM: TCP 协议;UDP 用 SOCK_DGRAM) 协议类型(IPPROTO_IP: IP ; IPPROTO_TCP :TCP)
  3. 拨号连接(此时连接成功)
    • connect() 成功时返回0
  4. 发送和接收数据
    • send(); 失败时返回-1 说明发送失败
    • recv(); 失败时返回-1 说明接收失败;返回0说明服务器关闭;大于0则接收成功
  5. 最后需要关闭socket释放资源
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
void Tcp_Client(void *pvparam)

{

    // 1. 等待 Wi-Fi 获取 IP 的信号

    xEventGroupWaitBits(WIFI_READY, WIFIREADY_BIT, pdFALSE, pdTRUE, portMAX_DELAY);

    ESP_LOGI("TCP", "Wi-Fi 已就绪,准备连接电脑...");

  

    char *tradata = "MYTCP Send";

    char recbufer[100];

  

    //填写服务器信息

    struct  sockaddr_in sockaddr;

    sockaddr.sin_addr.s_addr = inet_addr("192.168.1.18");

    sockaddr.sin_family = AF_INET;//ipv4 AF_INET6(ipv6)

    sockaddr.sin_port = htons(8080); //必须使用htons做字节序转换

  

    while (1)

    {

        //创建socket

        int sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);//地址(ipv4 ipv6) 套接字类型(SOCK_STREAM: TCP 协议;UDP 用 SOCK_DGRAM) 协议类型(IPPROTO_IP: IP ; IPPROTO_TCP :TCP)

        if(sock < 0)

        {

            ESP_LOGW("TCP","SOCK创建失败");

            vTaskDelay(pdMS_TO_TICKS(20));

            continue;

        }

  

        //拨号连接

        int res = connect(sock,(struct sockaddr *)&sockaddr,sizeof(sockaddr));

        if(res != 0)

        {

            ESP_LOGW("TCP","拨号连接失败");

            close(sock);//必须释放sock否则会泄露文件句柄

            vTaskDelay(pdMS_TO_TICKS(2000));

            continue;

        }

  

        ESP_LOGW("TCP","端口连接成功%s %d","192.168.1.18",8080);

  

        while (1)

        {

            //发送数据

            int write = send(sock,tradata,strlen(tradata),0);//最后一位默认是0

            if(write < 0)

            {

                ESP_LOGW("TCP","数据发送失败");

                vTaskDelay(pdMS_TO_TICKS(2000));

                break;

            }

  

            //接收数据

            int receive = recv(sock,recbufer,sizeof(recbufer) - 1,0);

            if(receive < 0)

            {

                ESP_LOGW("TCP","数据接收失败");

                vTaskDelay(pdMS_TO_TICKS(2000));

                break;

            }else if(receive == 0){

                ESP_LOGW("TCP","服务器关闭");

                vTaskDelay(pdMS_TO_TICKS(2000));

                break;

            }else{

                 recbufer[receive] = 0;//末尾补0,来作为字符串结尾

                ESP_LOGW("TCP","%s",recbufer);

            }

            vTaskDelay(pdMS_TO_TICKS(2000));

        }

  

        if(sock != -1){

            close(sock);

            vTaskDelay(pdMS_TO_TICKS(2000));

        }

    }

}

2.3

专注嵌入式开发,记录技术成长
使用 Hugo 构建
主题 StackJimmy 设计