1、ESP8266 SDK介绍
2、FreeRTOS工作原理
3、第一个任务hello word
4、第二个任务点灯
5、WiFi-STATION&AP连接
ESP8266 SDK介绍
1、SDK 目录结构
2、SDK API接口
3、编译工程模板
SDK 目录结构
SDK目录结构:
Bin目录:(重点使用的目录)
编译形成的BIN文件,可直接下载到Flash中
根目录下为官方提供的bin文件(一般烧写最新版本的bin文件:boot_v1.7.bin)
Upgrade为工程编译后生成的用户代码
documents目录:(重点使用的目录)
SDK 相关的文档或链接
PDF文档为API参考手册,相当于STM32的标准库
html网页版的API参考手册
driver_lib目录:(重点使用的目录)
ESP8266外设驱动代码
Driver:外设驱动源码
Include:外设驱动头文件
Makefile:外设驱动自动编译脚本
Make_lib.sh 外设驱动shell脚本
example目录:(重点使用的目录)
ESP8266示例代码
mqtt_demo:mqtt协议示例代码
openssl:OpenSSL接口功能代码
Project_template:工程模板
Smart_config: 智能联网示例代码(我们目前使用官方提供的这个示例代码)
spiffs: SPI文件系统代码
websocket_demo: WEB网络编程代码
Wifi_station_machine_demo: wifi站点示例代码
wps: wifi 保护设置示例代码
extra_include目录:ESP8266-xtensa内核接口(重点使用的目录)
include目录:SDK 自带头文件,包含了用户可使用的相关 API 函数及其他宏定义,用户无需修改。(重点使用的目录)
ld目录:链接时所需的脚本文件,如无特殊需求,用户无需修改(不需要了解)
lib目录:SDK 提供的库文件。(不需要了解)
third_party目录:乐鑫开放源代码的第三方库,当前包含 freeRTOS、 JSON、 lwIP、mbedTLS、 noPoll、 OpenSSL、SPIFFS 和 SSL。 (不需要了解)
tool目录:编译 BIN 文件所需的工具,用户无需修改(不需要了解)
SDK API接口
API接口:
序号 | 接口名称 | 接口说明 |
1 | WiFi Related APIs | WiFi相关的接口 |
2 | AirKiss APIs | AirKiss的接口 |
3 | SoftAP APIs | 软件无线接入点接口 |
4 | Station APIs | 站点接口 |
5 | Common APIs | 通用接口 |
6 | Force Sleep APIs | 休眠接口 |
7 | Rate Control APIs | 速率控制接口 |
8 | User IE APIs | 用户接口 |
9 | Sniffer APIs | 嗅探器接口 |
10 | WPS APIs | 无线安全设置接口 |
11 | Smartconfig APIs | 智能联网接口 |
12 | Misc APIs | 混合接口 |
13 | Spiffs APIs | SPI文件系统接口 |
14 | SSC APIs | SSC接口 |
15 | System APIs | 系统接口 |
16 | Boot APIs | 启动接口 |
17 | Upgrade APIs | 云端升级接口 |
18 | Software timer APIs | 软件定时器接口 |
19 | Network Espconn APIs | ESP网络接口 |
20 | ESP-NOW APIs | ESP接口 |
21 | Mesh APIs | 网状网络接口 |
22 | Driver APIs | 外设驱动接口 |
23 | PWM Driver APIs | 脉宽调制接口 |
24 | SPI Driver APIs | SPI通信接口 |
25 | GPIO Driver APIs | 通用IO接口 |
26 | Hardware timer APIs | 硬件定时器接口 |
27 | UART Driver APIs | 串口通信接口 |
编译工程模板
搭建app目录:
在SDK目录下新建app目录
cd 到examples目录下
拷贝smart_config下所有文件到app目录下
cd 到app目录下查看文件是否拷贝成功
修改gen_misc.sh:
vim 打开gen_misc.sh进行编辑
修改SDK_PATH为当前SDK路径(绝对)
修改BIN_PATH为当前BIN路径(绝对)
export SDK_PATH=$/home/esp8266/Share/ESP8266_RTOS_SDK-2.0.0
export BIN_PATH=$/home/esp8266/Share/ESP8266_RTOS_SDK-2.0.0/bin
Wq保存退出
修改Makefile:
因为分离了sdk和project目录,所以编译之前必须先指定一个 SDK_PATH 和 BIN_PATH,修改 ESP8266_RTOS_SDK/app 目录下的 makefile,添加以下内容:
parent_dir:=$(abspath $(shell pwd)/$(lastword $(MAKEFILE_LIST)))
parent_dir:=$(shell dirname $(parent_dir))
parent_dir:=$(shell dirname $(parent_dir))
SDK_PATH= $(parent_dir)
BIN_PATH=$(SDK_PATH)/bin
编译:
./gen_misc.sh
运行gen_misc脚本进行编译
编译配置:
FreeRTOS实时操作工作原理
1、FreeRTOS实时操作系统
2、FreeRTOS任务
3、FreeRTOS使用说明
FreeRTOS实时操作系统
前后台系统:
早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。
RTOS系统:
RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。实时操作系统又分为硬实时和软实时。硬实时要求在规定的时间内必须完成操作 ,硬实时系统不允许超时,在软实时里面处理过程超时的后果就没有那么严格。
在实时操作系统中,我们可以把要实现的功能划分为多个任务,每个任务负责实现其中的一部分,每个任务都是一个很简单的程序,通常是一个死循环。
RTOS操作系统:FreeRTOS,UCOS,RTX,RT-Thread,DJYOS等。
RTOS操作系统的核心内容在于:实时内核。
可剥夺型内核:
可剥夺内核顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。
RTOS的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其他任务,这个是内核的多任务管理能力。多任务管理给人的感觉就好像芯片有多个CPU,多任务管理实现了CPU资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时应用。
RTOS工作机制:
FreeRTOS介绍:
FreeRTOS是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。FreeRTOS提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
FreeRTOS特点:
FreeROTS开源
FreeRTOS免费
FreeRTOS是很多第三方组件钦定的系统!
FreeRTOS使用:
FreeRTOS下载: http://www.freertos.org/
FreeRTOS还是有一定难度的,在学习的过程中难免会遇到看不懂的东西,如果遇到不懂的就先不要管,开发ESP8266只需要学会怎么调用FreeRTOS的API函数
对C语言的要求,需要了解指针、结构体、数据结构中的链表等。
FreeRTOS任务
FreeRTOS任务特性:
简单
没有使用限制
支持抢占
支持优先级
每个任务都拥有堆栈导致了 RAM 使用量增大
如果使用抢占的话的必须仔细的考虑重入的问题
FreeRTOS任务状态:运行态、就绪态、 阻塞态、挂起态
FreeRTOS任务优先级:
任务优先级决定了任务的执行优先级别,在FreeRTOS中任务优先级可选范围为:
0 ~ configMAX_PRIORITIES-1
数字越大,优先级越高!
FreeRTOS任务创建函数:
头文件:task.h
portBASE_TYPE xTaskCreate (
pdTASK_CODE pvTaskCode, 指向任务的实现函数的指针。效果上仅仅是函数名
const portCHAR * const pcNane, 具有描述性的任务名。FreeRTOS 不会使用它。
unsigned portSHORT usStackDepth, 指定任务堆栈的大小(4个字节为单位,如该项填写256表示堆栈有1024个字节)
void *pvParameters, 指针用于作为一个参数传向创建的任务
unsigned portBASE_TYPE uxPriority, 任务运行时的优先级(重要)
xTaskHandle *pvCreatedTask 用于传递任务的句柄,可以引用从而对任务进行其他操作。(一般不使用)
)
FreeRTOS任务延时函数:
头文件:task.h
void vTaskDelay (//如果填写的是1秒钟,实际返回的任务往往大于1秒钟(软实时)
portTickType xTicksToDelay 时间数量,调用任务应该锁住的时间片周期
)
void vTaskDelayUntil (//精准延时(硬实时)
portTickType *pxPreviousWakeTime, 指定一个变量来掌握任务最后开启的时间, 第一次使用时必须
使用当前时间来初始化, 在 vTaskDelayUntil 中,这个变量是自动修改的
portTickType xTimeIncrement 循环周期时间
)
FreeRTOS任务删除函数:
头文件:task.h
void vTaskDelete (
xTaskHandle pxTask 处理要删除的任务。传递 NULL 将删除自己
)
FreeRTOS任务实现函数模板:
void ATaskFunction( void *pvParameters )
{
/* 可以像普通函数一样定义变量。用这个函数创建的每个任务实例都有一个属于自己的iVarialbleExample变
量。但如果iVariableExample被定义为static,这一点则不成立 – 这种情况下只存在一个变量,所有的任务实
例将会共享这个变量。 */
int iVariableExample = 0;
/* 任务通常实现在一个死循环中。 */
for( ;; )
{
/* 完成任务功能的代码将放在这里。 */
}
/* 如果任务的具体实现会跳出上面的死循环,则此任务必须在函数运行完之前删除。传入NULL参数表示删除
的是当前任务 */
vTaskDelete( NULL );
}
FreeRTOS任务优先级函数:
头文件:task.h
unsigned portBASE_TYPE uxTaskPriorityGet (//获取优先级
xTaskHandle pxTask 需要处理的任务. 当传递 NULL 时,将返回调用该任务的优先级
)
void vTaskPrioritySet (//设置优先级
xTaskHandle pxTask , 需要设置优先级的任务。当传递 NULL,将设置调用任务的优先级
unsigned portBASE_TYPE uxNewPriority 任务需要设置的优先级
)
FreeRTOS任务挂起函数:
头文件:task.h
void vTaskSuspend (//比如低功耗任务下需要调用该函数挂起其他任务
xTaskHandle pxTaskToSuspend 处理需要挂起的任务。传递 NULL 将挂起调用此函数的任务
)
void vTaskResume (//比如退出低功耗时需要运行其他任务,则调用该函数
xTaskHandle pxTaskToResume 就绪任务的句柄
)
FreeRTOS使用说明
FreeRTOS使用:
RTOS SDK 的系统任务优先级为 15 ,创建任务的接口 xTaskCreate 为 freeRTOS 自带接口,使用 xTaskCreate 创建任务时,任务堆栈设置范围为 [176, 512]
在任务内部如需使使用度超过 60 的大数组,建议使用malloc 和 free 的方式操作,否则,大数组将占用任务的堆空间;
SDK 底层已占用部分优先级: pp task 优先级 13,精确 ets timer 线程优先级 12, lwip task优先级 10, freeRTOS timer 优先级 2, idle 优先级 0;
可供用户线程使用的优先级为 1 ~ 9,请勿修改 FreeRTOSConfig.h,优先级由 SDK 底层决定,此处修改头文件并不能生效。
第一个任务hello word
1、Source Insight安装
2、功能分析
3、功能实现
Source Insight安装
功能分析
使用freeRTOS新建一个任务,定时1秒,串口打印hello word
功能实现
新建hello word工程目录:
在SDK目录下新建helloword:
拷贝app目录下所有文件到helloword:
SourceInsight下新建工程:
代码实现:
在user_main.c下实现helloword任务(打开user_main.c文件进行编码:user_main.c文件为函数入口)
在user_init下新建helloword任务
/******************************************************************************
* FunctionName : ATaskHelloWord
* Description : hello word
* Parameters : none
* Returns : none
*******************************************************************************/
void ATaskHelloWord( void *pvParameters )//helloword任务实现函数
{
int iVariableExample = 0;
for(;;)
{
printf("hello word!\n");
vTaskDelay(100);//延时1秒钟
}
vTaskDelete( NULL );
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
printf("SDK version:%s\n", system_get_sdk_version());
/* need to set opmode before you set config */
// wifi_set_opmode(STATION_MODE);
// xTaskCreate(smartconfig_task, "smartconfig_task", 256, NULL, 2, NULL);
xTaskCreate(ATaskHelloWord, "hello word", 256, NULL, 2, NULL);//helloword任务创建
}
功能调试:
编译文件
烧写bin文件
使用串口调试工具,设置波特率为74880(SDK默认的boot的uart配置就是74880),查看打印日志
第二个任务点灯
1、功能分析
2、原理图分析
3、功能实现
功能分析
使用freeRTOS新建一个任务,使nodeMcu板上LED灯,1秒钟闪烁一次
原理图分析
功能实现
新建led工程目录:
在SDK目录下新建led目录:
拷贝helloword目录下所有文件到led目录下:
添加外设驱动文件:
led目录下新建driver目录
拷贝driver_lib/driver下所有文件到led/driver下
添加外设驱动文件:
拷贝driver_lib/include下所有文件到led/include下:
修改Makefile:
添加工程编译子目录driver:
生成libdriver.a静态库:
wq保存
Sourceinsight配置:
代码实现:
在user_main.c下,添加
Led初始化
Led任务
在user_init下
使用led初始化
新建led任务
Led初始化:
包涵gpio.h
配置GPIO16为输出模式
设置GPIO16为高电平输出
user_main.c
#include "gpio.h"
/******************************************************************************
* FunctionName : Led_init
* Description : led初始化 Parameters : none
* Returns : none
*******************************************************************************/
void Led_init( void )
{
gpio16_output_conf();//GPIO16设置为输出模式
gpio16_output_set(1);//GPIO16引脚拉高,此时灯灭
}
Led任务:
user_main.c
/******************************************************************************
* FunctionName : ATaskLed
* Description : Led 实现函数
* Parameters : none
* Returns : none
*******************************************************************************/
void ATaskLed( void *pvParameters )//任务实现函数
{
int iVariableExample = 0;
for(;;)
{
gpio16_output_set(0);
printf("ledon\n");
vTaskDelay(100);
gpio16_output_set(1);
printf("ledoff\n");
vTaskDelay(100);
}
vTaskDelete( NULL );
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
printf("SDK version:%s\n", system_get_sdk_version());
Led_init();
/* need to set opmode before you set config */
// wifi_set_opmode(STATION_MODE);
//xTaskCreate(smartconfig_task, "smartconfig_task", 256, NULL, 2, NULL);
xTaskCreate(ATaskLed, "LED", 256, NULL, 2, NULL);//添加任务
}
WiFi-Station&AP连接
1、功能分析
2、Station功能实现
3、AP功能实现
功能分析
配置WiFi为Station模式,连接到本地的WiFi网络里
配置WiFi为AP模式,PC机连接到WiFi AP下
Station功能实现
WiFi Station入网条件:
本地有WiFi网络
SSID:WiFi网络名称
PASSWORD:WiFi入网密码
WiFi Station入网流程:
新建Station工程目录:
在SDK目录下新建Station目录
拷贝led目录下所有文件到Station目录下
Sourceinsight配置:
代码实现:
在user_init下完成WiFi Station功能开发:
user_main.c
#define SSID "chuangkexueyuan"//wifi账号
#define PASSWORD "makeru2017"//wifi密码
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
printf("SDK version:%s\n", system_get_sdk_version());
Led_init();
wifi_set_opmode(STATION_MODE);//配置WiFi为Station模式
struct station_config *config = (struct station_config *)\
zalloc(sizeof(struct station_config));//动态的分配内存空间
sprintf(config->ssid,SSID);
sprintf(config->password,PASSWORD);
wifi_station_set_config(config);//配置设置到寄存器里面
free(config);//释放动态分配的内存
wifi_station_set_auto_connect(TRUE);//启动wifi的一键连接
/* need to set opmode before you set config */
// wifi_set_opmode(STATION_MODE);
//xTaskCreate(smartconfig_task, "smartconfig_task", 256, NULL, 2, NULL);
xTaskCreate(ATaskLed, "LED", 256, NULL, 2, NULL);
}
验证测试:
烧写固件
复位查看串口日志,获取到路由器分配的IP
AP功能实现
WiFi AP建立条件:
SSID:WiFi网络名称(定义为自己的名字)
PASSWORD:WiFi入网密码(123456789)
加密模式:WAP2_PSK
WiFi AP建立流程:
新建AP工程目录:
在SDK目录下新建AP目录
拷贝Station目录下所有文件到AP目录下
Sourceinsight配置:
代码实现:
user_main.c
#define SSID "liuzhengdao"
#define PASSWORD "123456789"
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
printf("SDK version:%s\n", system_get_sdk_version());
Led_init();
wifi_set_opmode(SOFTAP_MODE);//设置为AP模式
struct softap_config *config = (struct softap_config *)\
zalloc(sizeof(struct softap_config));
wifi_softap_get_config(config);//获取当前参数
sprintf(config->ssid,SSID);//传入自己定义的网络名称
sprintf(config->password,PASSWORD);//传入自己定义的网络密码
config->authmode = AUTH_WPA_WPA2_PSK;//授权加密方式
config->ssid_len = 0;//设置网络名称长度为0,表示网络名称字符串中遇到'\0'时结束。
config->max_connection = 4;//设置最大连接数
wifi_softap_set_config(config);//设置到寄存器
free(config);//释放动态存储
//wifi_station_set_auto_connect(TRUE);
/* need to set opmode before you set config */
// wifi_set_opmode(STATION_MODE);
//xTaskCreate(smartconfig_task, "smartconfig_task", 256, NULL, 2, NULL);
xTaskCreate(ATaskLed, "LED", 256, NULL, 2, NULL);
}
验证测试:
烧写固件
复位查看串口日志,PC连接AP,获取AP分配的IP地址