uart配网,led灯显示联网状态
例程详细讲解
// uart对esp32配网,led显示联网状态:led常亮即为连接成功,灭反之
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
//gpio头文件
#include <stdio.h>
#include "driver/gpio.h"
#include "sdkconfig.h"
//gpio头文件结尾
//uart头文件
#include "driver/uart.h"
#include "esp_log.h"
//uart头文件结束
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
//uart宏定义
#define ECHO_TEST_TXD 4
#define ECHO_TEST_RXD 5
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE )
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE )
#define ECHO_UART_PORT_NUM 2
#define ECHO_UART_BAUD_RATE 115200
#define ECHO_TASK_STACK_SIZE 4096
//串口的测试
static const char *TAG = "UART TEST";
//给定存储的大小
#define BUF_SIZE (4096)
//uart宏定义结束
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
//gpio宏定义
#define LED_R 2
//gpio宏定义结束
//gpio开始配置
void Led_Init(void)
{
//选择 IO
gpio_pad_select_gpio(LED_R);
//设置 IO 为输出
gpio_set_direction(LED_R, GPIO_MODE_OUTPUT);
}
//gpio结束配置
static int s_retry_num = 0;
//在调度事件时调用处理函数程序
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();//WiFi连接
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
wifi_event_sta_disconnected_t *disconnected = (wifi_event_sta_disconnected_t *)event_data;
ESP_LOGI(TAG, "STA disconnect reason %d", disconnected->reason);
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP"); //重新尝试连接AP
} else {
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");//连接AP失败
//led初始化
Led_Init();
//连接失败时电平拉低,led不亮
gpio_set_level(LED_R, 0);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { //工作站从连接的AP获取IP
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
//连接成功后把led电平拉高,led亮
gpio_set_level(LED_R, 1);
}
}
//将处理好的字符串信息发给WiFi
void wifi_init_sta(char* ssid,char* pwd)
{
//创建一个新的事件组
s_wifi_event_group = xEventGroupCreate();
//创建一个 LwIP 核心任务,并初始化 LwIP 相关工作。
ESP_ERROR_CHECK(esp_netif_init());
//事件初始化
ESP_ERROR_CHECK(esp_event_loop_create_default());
//创建有 TCP/IP 堆栈的默认网络接口实例绑定 station
esp_netif_create_default_wifi_sta();
//将配置初始化为默认的值,确保下面的函数不出错
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
//创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序。
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
//将事件处理程序的实例注册到默认循环。
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID, //注册处理程序的事件id
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP, //工作站从连接的AP获取IP
&event_handler,
NULL,
&instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
//设置模式为WPA2
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
},
};
//将读取到的ssid和password复制给WiFi初始化
memcpy(wifi_config.sta.ssid,ssid,strlen(ssid));
memcpy(wifi_config.sta.password,pwd,strlen(pwd));
//打印出ssid和pwd的信息
printf("ssid:%s,pwd:%s\n",ssid,pwd);
//设置WiFi的模式为station
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
//调用已经设置好的WiFi id和密码
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
//开始启动
ESP_ERROR_CHECK(esp_wifi_start() );
}
//uart开始配置
static void echo_task(void *arg)
{
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE, //波特率大小
.data_bits = UART_DATA_8_BITS, //数据位
.parity = UART_PARITY_DISABLE, //禁用奇偶效验位
.stop_bits = UART_STOP_BITS_1, //停止位
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //禁用硬件流控模式
.source_clk = UART_SCLK_APB, //设置时钟源为SCLK_APB
};
int intr_alloc_flags = 0; //分配中断的标志
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
//端口号、tx和rx的环形缓冲区大小
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
//调用已经配置好数据的函数uart_config
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
//设置引脚
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));
//给data分配一个空间,便于存数据,空间大小为BUF_SIZE
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
//给ssid数组分配一个空间,便于存储数据
char ssid[32] = {0};
//给pwd数组分配一个空间,便于存储数据
char pwd [64] = {0};
// int i =0;
while (1) {
//将外界读取到的数据存到data中
int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_RATE_MS);
//读取存到data的数据,长度为int len读取到的长度
uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len);
if (len) {
//data大于0即读进下面的程序
data[len] = '\0';
//将读入的data用.分开传输,strtok为分解字符串;char *strtok(char *str, const char *delim),delim为分隔符,在这里指的是.
char *p = strtok((char *)data,".");
//复制指针p内.前面所有的值,strlen意为计算字符串p中的长度,直到空结束字符,不包括空,在这里意为到.结束
memcpy(ssid,p,strlen(p));
printf("ssid:%s\r\n",ssid);
p = strtok(NULL,".");
//复制指针p内.后面所有的值
memcpy(pwd,p,strlen(p));
printf("password:%s\r\n",pwd);
//以.结尾,避免出现错误
p = strtok(NULL,".");
break;
}
}
wifi_init_sta(ssid,pwd);
vTaskDelete(NULL);
}
//uart配置结束
void app_main(void)
{
//uart主函数
xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL);//创建一个事件,设置事件大小,
//uart结束
//初始化默认的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()); //清除默认的nvs内容
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
}
总结
本人也是一个学习的过程,在这段程序中收益良多,在此发文既跟大家分享,也是我自己记录的一个学习过程,中间若有不足还见谅。
在这段程序中大多都是用的idf官方例程,其中有uart和station的例程,还包含了一些简单的gpio的介绍,因为其中的gpio只是为了点灯,中断并没有用到,所有介绍的会相对少一些,在这些官方例程中花费最多时间的是uart,在实现通讯时卡了很久,不过好在还是做出来了,从中也学到很多东西,后续还要继续加油!