零之前言
这里先说一下,这只是我个人的对ESP8266 rtos3.0+
版本的整理与记录,可能与其他人的有差别。本人能力有限,如果有问题,请斧正,谢谢。
一.内核类
0.说明:
创建一个task,就类似于创建一个线程,然后我能力有限,不好说清楚那种感觉。。。
可以看看官方文档,挺好理解的FreeRTOS
1.创建、销毁:
创建:
static BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
可能看起来太复杂,简化一下:
xTaskCreate(创建线程的函数, "task的名字", 1024(栈大小), NULL(创建时运行的程序), 10(优先级), NULL(线程句柄));
一般来说,我们只需要用前两个参数就可以了:xTaskCreate(echo_task, "uart_echo_task", 1024, NULL, 10, NULL);
更多的内容,可以看官方文档:
官方文档-xTaskCreate
销毁:
vTaskDelete(TaskHandle_t xTaskToDelete)
传入指针就行
2.延时
这样用就行vTaskDelay(2000 / portTICK_PERIOD_MS);
延时两秒
3.事件组
①创建
官方文档翻译:
在FreeRTOS实施内部,事件组使用[小]内存块,其中存储了事件组的结构。 如果使用xEventGroupCreate()创建事件组,则所需的内存将自动在xEventGroupCreate()函数内部动态分配。
事件标志组可以实现多任务间的任务同步,简单来说就是在不同的任务间传递简单的标志位。可以用于一些任务调用同一个反馈子程序。
EventGroupHandle_t xxx = xEventGroupCreate();
②销毁
在创建了之后注册系统事件,最后销毁vEventGroupDelete(xxx);
二.wifi类
1.station模式(模块去连接wifi)
初始化wifi
当然你在以下代码,创建一个xEventGroupCreate()
事件组。
tcpip_adapter_init();
esp_event_loop_create_default();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
wifi_config_t wifi_config = {
.sta = {
.ssid = "your wifi ssid",
.password = "your wifi's password"
},
};
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
esp_wifi_start();
esp_wifi_connect(); //connect wifi
如果需要重连回调,则需要注册:
esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
并且编写:event_handler:
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) {
if (s_retry_num < 5) { // retry times
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
} else {
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");
}
}
2.AP模式(单片机等着被别人连)
代码:
void wifi_init_softap()
{
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = "Wifi_ssid",
.ssid_len = strlen("Wifi_ssid"),
.password = "wifi_password",
.max_connection = 99,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
如果需要获取mac地址,则注册wifi_event事件:
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
如果需要获取ip地址,本来有个IP_event有代码,结果试了试,8266会重启,不知道是我哪里搞错了,后面再修改试试,破案了,官方原话回复:
I see function tcpip_adapter_dhcps_cb in tcpip_adapter_lwip.c sends the event with the client IP address in event_info via esp_event_send(&evt), but the mapping between the legacy and new event system doesn’t map the event_info - it’s missing the ARGS HANDLE_SYS_EVENT(IP, AP_STAIPASSIGNED)
They have it working properly in ESP-IDF.
需要将event_send_compat.c
94 lines 改为HANDLE_SYS_EVENT_ARG(IP, AP_STAIPASSIGNED, ap_staipassigned);
,即可使用该事件:
else if (event_id == IP_EVENT_AP_STAIPASSIGNED){
ip_event_ap_staipassigned_t* event = (ip_event_ap_staipassigned_t*) event_data;
ESP_LOGI(TAG,"got ip form event loop:%s", ip4addr_ntoa(&event->ip));
}
三.IO类
1.输入与输出
需要用到#include "driver/uart.h"
①.输入
初始化函数:
static void gpio_input_init(int pin){
gpio_config_t io_conf;
io_conf.pin_bit_mask = (1ULL << pin);
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = 1;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
}
应用初始化:gpio_input_init(14);
获取电平:gpio_get_level(14)
②.输出
初始化函数:
static void gpio_output_init(int pin){
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << pin);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
}
应用初始化:gpio_output_init(15);
设置低电平:gpio_set_level(15,0);
2.串口
①.初始化
配置代码:
static void uart_init(int bord, int Buf){
uart_config_t uart_config = {
.baud_rate = bord,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_0, &uart_config);
uart_driver_install(UART_NUM_0, Buf * 2, 0, 0, NULL, 0);
}
应用初始化:uart_init(74880,1024);
②.串口输出:
static void uart_print(char* str){
uart_write_bytes(UART_NUM_0, (const char*)str, strlen(str));
}
写uart_print("USART TEST\r\n");
四.socket类
1.tcp_client
这是官方的代码,直接创建以你个xtask就可以了。然后稍作修改即可。
static void tcp_client_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family;
int ip_protocol;
static const char *payload = "Message from ESP32 ";
while (1) {
vTaskDelay(2000 / portTICK_PERIOD_MS);
struct sockaddr_in destAddr;
destAddr.sin_addr.s_addr = inet_addr("192.168.249.187");
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(3333);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created");
int err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
}
ESP_LOGI(TAG, "Successfully connected");
while (1) {
vTaskDelay(2000 / portTICK_PERIOD_MS);
int err = send(sock, payload, strlen(payload), 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
break;
}
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
// Error occured during receiving
if (len < 0) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
break;
}
// Data received
else {
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
send(sock, rx_buffer, len - 1, 0);
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
}
}
vTaskDelete(NULL);
}
2.tcp_server
static void tcp_server_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family;
int ip_protocol;
while (1) {
struct sockaddr_in destAddr;
destAddr.sin_addr.s_addr = htonl("0.0.0.0");
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(3333);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created");
int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket binded");
err = listen(listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket listening");
struct sockaddr_in sourceAddr;
uint addrLen = sizeof(sourceAddr);
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket accepted");
while (1) {
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
// Error occured during receiving
if (len < 0) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
break;
}
// Connection closed
else if (len == 0) {
ESP_LOGI(TAG, "Connection closed");
break;
}
// Data received
else {
rx_buffer[len] = 0;
ESP_LOGE(TAG, "%s", rx_buffer);
//int err = send(sock, rx_buffer, len, 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
break;
}
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
}
}
vTaskDelete(NULL);
}