环境
AiThinkerIDE_0.5
flash_download_tools
AiThinker Serial Tool V1.2.3
CH341SER
(记个笔记,自用)
模板制作
根据乐鑫公司通用模板剪裁制作自己的专用模板,日后只需填入代码即可。
乐鑫公司提供的模板是SDK(software Development Kit)
SDK:供软件使用的软件。(封装好的软件,可以被软件调用。先这么理解)
公司提供的往往是SDK集合体,包括SDK,技术文档,范例,调试工具等等。(教你怎么用的)
API(Application Programming Interface):是一个函数,用于实现某种功能(函数不是软件,先这么记住)
SDK会配套API参考手册,罗列SDK提供的所有API函数(如果没有,骂娘就对了。)
SDK是奶茶的话,API就是吸管。(喝奶茶不能把杯子切开吧,用某个功能不能手搓吧。)
裁剪
文件裁剪
ESP8266_NONOS_SDK-2.2.1.zip
提取压缩包到当前文件夹(我不知道为啥当前文件夹)
bin文件夹存放编译生成的二进制文件(有些懵)。也就是可以下载到8266中执行的文件
documents 存放的是SDK相关文档。(readme.txt,就这个文档。截图很麻烦的)
driver_lib存放8266片上外设的驱动文件(就是.c文件和.h文件,每个外设一个。应该看的懂吧,大概)
examples 存放示例代码的,懵逼了就进去翻翻
include 保存SDK自带的头文件,保存了API函数和各种宏定义。(我不知道啥是宏定义,我只认为是起别名,大家应该都一样吧)
ld 保存了链接时需要使用的脚本文件
lib 存放的是SDK提供的库文件
third_party 存放第三方的示例代码(鬼知道第三方这个词让我有多痛苦,就和其他这俩字一样)
tools 保存的是编译bin文件需要的工具
这些就是一个完整的SDK,至少乐鑫提供的是这些。(我觉得乐鑫很牛逼)
删去driver_lib里面的makefile,不带后缀的那个
删去那个第三方(third_party)整个删去
把examples里的wps文件剪切至上层目录(examples在的那个文件夹)并重命名为app,然后删去examples;
代码裁剪与代码编译
1.打开IDE,资源管理器中鼠标右键选择import选项(就是最左边的那个大框框,框的左上角写着Project Explorer的)
2.弹出对话框后点击 Next 然后点击Browse按钮,找到1.3模板制作文件选上
3.取消C++前面的对勾
4.选择Cygwin GCC
5.点击Finished
OK,结束
资源管理器里就能看到1.3模板制作工程了
展开这个工程,再展开app文件夹下的user文件夹,找到user_main.c,打开
删除122~130行的代码
删除28~61行的代码
用不到这些
剩下的就别动了
(截图很麻烦的,先这样吧。你以后加吧。配环境又不是经常性的,实在不行看教程)
保存所有修改
再在1.3模板制作上点击鼠标右键,选择Clean project。
再在1.3模板制作上点击鼠标右键,选择Build project。
编译完成
eagle.flash.bin-------->0x00000
eagle.irom0text.bin---->0x10000
提示框里会显示这两个
没提示就是有错
ok,完成
模板使用
模板使用
1.导入SDK工程模板,添加代码,编译声称8266二进制文件
2,利用flash下载工具将文件下载进8266
3,利用串口调试助手接收并显示8266回传信息
4,总结API参考手册的编写特点,阅读和使用方法,体会SDK开发的优越性
编写与编译
先复制一份1.3模板制作,重命名为1.4模板使用。
用同样的操作导入资源管理器
打开1.4的 user_main.c,找到user_Init()函数
打开8266的API参考手册
找到3.3.42 os_printf
可以看到这个函数的参数是(const char *s),是字符串的指针
在user_Init(){
os_printf("\n\n\n");
os_printf("hello word\n");
os_printf("\n\n\n");
}
SDK提供了大量API函数,根本记不住,所以看得懂参考手册的描述和参数就行
flash工具下载代码
双击flash下载工具,选择esp8266,可以看到一个非常复杂的界面,之所以复杂是因为8266没有存储器,要外界w25q系列存储器,所以存储器大小可以根据项目代码的大小选择不同容量。
有512k,1M,2M,4M,8M,16M
8266有多个二进制文件,不想经典51只有一个。
这些二进制文件需要写入到不同的地址。因此界面复杂。
(比较乱,要适应下)
开发板上的8266使用的是32Mbit,也就是4MByte。
需要下载4个bin文件
eagle_flash保存必要固件
eagle_irom0text保存用户编写的程序
esp_init_data_default保存默认射频参数
blank 保存系统参数信息
blank要下载两次
标红的地方一般不需要变动。(COM4哪里看个人用的哪个就行)
串口调试助手
调整串口号和波特率如图所示
按开发板复位按钮,助手显示hello word
参考手册的结构
前两章是前言和对SDK简单介绍
第三章介绍了基本的API函数
第四章介绍了联网的API函数
第五章介绍解析json字符串需要用到的API函数
第六章归纳了8266中出现的结构体和宏定义
第七章介绍片上资源驱动相关API函数
附录 补充说明
功能综述
8266即是MCU即单片机
IO,定时器,PWM,UART,IIC,人机交互接口等等
只是8266具备wifi功能
51是对寄存器的配置来使用资源
8266则使用封装好的API函数使用。(反正就是操作简单了)
GPIO点灯
//点灯
//GPIO接口设置为输出接口
//输出控制信号
//点亮开发板上的LED
//点灯成功
GPIO:通用输入输出接口,单片机的触手
接口是通用的,接口的功能是可变的
user_init(void)
{
//点灯
//GPIO接口设置为输出接口
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);
//输出控制信号
//点亮开发板上的LED
GPIO_OUTPUT_SET(GPIO_ID_PIN(4), 1);
GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);
GPIO_OUTPUT_SET(GPIO_ID_PIN(5), 0);
//点灯成功
}
GPIO复用
8266共有17个管脚,这些管脚可以与其他功能复用,如IIC UART PWM IR等
开发者仅能使用其中八个。用掉了九个管脚。
SDIO占据六个,SDIO链接外部存储器,是必不可少的。即IO6/7/8/9/10/11是必须分配给外部存储器的。
UART占据两个,UART0(IO3-RX,IO1-TX)用来下载程序
GPIO16:GPIO16不属于GPIO模块,用于深度睡眠时唤醒整个模块
应用函数和回调函数
应用函数是自己封装的函数
回调函数:事件调用的一种函数,事件发生时调用对应的回调函数(我想到了中断函数)
中断函数是特殊的回调函数
写应用函数就如同写c函数一样
写回调函数则需要特定的,用来触发回调函数的函数 例如 system_init_done_cb();
将函数名写入括号,可以在系统初始化时调用
软件定时器
定时器就是计数器,(学过数电的会秒懂)
轮询:如车转轮般一轮一轮的询问
轮询工作模式时,API参考手册不建议开发者采用while循环+延时函数的模式
浪费了微控制器
定时器帮助机器完成重复劳动,帮助人们实时获取温湿度数据
8266相关API函数:
关闭定时器:os_timer_disarm
设定定时器回调函数:os_timer_setfn
开启定时器:os_timer_arm
1.导入一个模板,并开始编程
2.//初始化定时器
//关闭定时器,防止出错
//确定回调函数
//开启定时器
/*
* ESPRESSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "osapi.h"
#include "user_interface.h"
os_timer_t soft_timer_1;//配置定时器的结构体
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
void soft_timer1_cb(void){//回调函数
os_printf("\n\n\n");
os_printf("helloword!!");
os_printf("\n\n\n");
}
void ICACHE_FLASH_ATTR
user_init(void)
{
//初始化定时器
os_timer_disarm(&soft_timer_1);//关闭定时器,防止出错
//确定回调函数
os_timer_setfn(&soft_timer_1,(os_timer_func_t *)soft_timer1_cb,NULL);//回调函数的格式必须强制转换
//开启定时器
os_timer_arm(&soft_timer_1,5000,1);//定时5秒
}
只看user_Init和soft_timer1_cb就行。
打开串口助手,即可查看效果演示
硬件定时器
和软件定时器实现效果相同
软件定时器是模拟出来的定时器,就和触屏手机的键盘一样,并不是真实存在的。
硬件定时器则是真实存在一个定时器,就和按键手机的键盘一样,是真实存在的
使用硬件定时器需要三步
1,初始化硬件定时器,hw_timer_Init
中断源分为两个,一个是NMI(最高级中断,可以打断其他中断),一个是FRC1(普通中断,不能打断中断)
2,设定硬件中断定时器的回调函数,hw_timer_set_func
3,开启硬件中断定时器,hw_timer_arm
优先使用软件定时器,除非对精度要求很高,且时间较短
定时编程
void hw_timwe_cb(){
os_printf("\n\n\n");
os_printf("hello word222\n");
os_printf("\n\n\n");
}
void ICACHE_FLASH_ATTR
user_init(void)
{
hw_timer_init(0,1);//FRC中断源,重复计时
hw_timer_set_func(hw_timwe_cb);//设置回调函数
hw_timer_arm(1000000);//微秒
}
PWM呼吸灯
PWM不仅可以控制灯的明暗变化,还可以控制电机的转动速度,舵机的转动角度
PWM有两个重要参数,period(周期),duty(占空比)
几乎所有的操作都围绕这两个参数
SDK里提供了七个PWM相关的API函数,完成呼吸灯则需要其中三个函数
初始化PWM,PWM_Init(初始化PWM,包括GPIO选择,周期和占空比,目前仅仅支持调用一次)
设置占空比,pwm_set_duty
PWM开始,pwm_start,每次更新PWM设置之后,都要重新调用本接口重新进行计算
/*
* ESPRESSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "osapi.h"
#include "user_interface.h"
os_timer_t soft_timer1;//定时器结构体变量
u32 io_info[3][3]={//用于保存IO引脚信息的二维数组
{PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2,2},//引脚名,引脚功能,引脚编号
{PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4,4},
{PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5,5}
};
u32 duty[3]={0,0,0};
u32 i=0,j=1;//占空比的递增方向,递增大小
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
void soft_timer1_cb(void){
//设定每个通道的占空比的高电平时间
//注意duty的取值范围(周期*1000/45),周期为1000时,duty最大22222
duty[0] = i*400;
duty[1] = i*400;
duty[2] = i*400;
//将占空比的值设置到对应的通道上
//调用API函数pwm_set_duty设置对于pwm引脚的占空比
pwm_set_duty(duty[0],0);
pwm_set_duty(duty[1],1);
pwm_set_duty(duty[2],2);
//让各个PWM通道,按照新的设置工作
//调用API函数pwm_start按新的占空比输出pwm波形
pwm_start();
//判断占空比有没有到达最大值或最小值
if(i==60){
j=-1;
}
if(i==0){
j=1;
}
i=i+j;
}
void ICACHE_FLASH_ATTR
user_init(void)
{
pwm_init(1000,duty,3,io_info);
os_timer_disarm(&soft_timer1);
os_timer_setfn(&soft_timer1,(os_timer_func_t *)soft_timer1_cb,NULL);
os_timer_arm(&soft_timer1,20,1);
}
呼吸灯程序
UART
UART0在默认状态下,40M晶振时,波特率115200。26M晶振时,波特率74880。
uart_init函数可以设置两个UART的波特率。包含两个参数,第一个参数设置UART0的波特率。
第二个参数设置UART1的波特率。
串口作为一个硬件资源,我们也要加载驱动程序。包含三个文件,uart.c,uart.h,uart_register.h
IIC
IIC是一种简单,双向,二线制,短距总线。为8266等MCU和外围芯片间的短距离通信提供简易的互联方式。
理论上,两根线上可以接127个传感器
微控制器与哪个传感器通讯通过传感器内部地址来区分。
IIC通讯过程的控制主要产生五种状态
1.起始状态
2.停止状态
3.主机应答从机状态
4.主机非应答从机状态
5.主机检查从机应答状态
这五种状态都是通过SDA和SCL两根数据线高低电平的不同组合来实现的
当SDA处于下降沿,SCL处于高电平,IIC开始
当SDA处于上升沿,SCL处于高电平,IIC停止
在SCL的第九个时钟上,SDA完成高-低-高的跳变、或者说在SCL的第九个时钟前完成高-低的跳变,第九个时钟后完成低到高的跳变。即是IIC主机应答ACK
在SCL的第九个时钟上,SDA维持高电平不变,即是完成IIC主机非应答。若是非应答,表明主机强行停止从机的数据发送。
主机在SCL的第九个时钟上,检查SDA的状态,SDA低则从机数据接收成功,SDA高则从机数据接收失败
IIC的传输过程一定是开发板发起的。无论是主机向从机发送还是从机向主机发送,都是主机发起的。
第一个字节决定数据是发送给谁的,字节中的七位用作地址,所以理论上有2^7-1个从机
第八位决定读写的方向,低电平表示数据是给传感器的。第一个字节发出后,也就是第九个时钟上,被寻址的传感器要回复一个ACK应答信号,开发板会检查是否有ACK应答信号。若是检测到了,就会开始发送数据。每发送一个字节,传感器就要应答一下(在第九个时钟上)。传输完成后,就要结束数据的传输。
读取数据时,第一个字节的最后一位变成了高电平,表明开发板想从从机读取数据,故发送第一个字节后,主机转为接收状态等待接收数据。传感器收到寻址信号后,就会将数据发送到IIC总线上。当数据传输完成,开发板会发出NACK信号,让传感器释放总线,然后发出停止信号。
IIC接口作为一种硬件资源,同样需要驱动和同时还需要调用初始化API函数
开发板可以向AHT10发送三种命令
1.初始化命令——1110’0001——E1
2,触发测量 ——1010’1100——AC
3,软复位 ——1011’1010——BA
AHT10的温湿度测量和读取温湿度数据是分两步进行的并不是说启动了一次测量AHT10就会主动将温湿度数据发送给开发板。
启动一次测量后,需要调用一次读取温湿度的函数,从AHT10中获取温湿度
在获取温湿度前,还需要调用获取AHT10状态的函数,检查AHT10是否完成测量工作只有完成测量才能获取温湿度数据
//触发测量函数
//检查状态函数
//读取数据函数
IIC接口温湿度采集
/*
* ESPRESSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "osapi.h"
#include "user_interface.h"
#include "driver/i2c_master.h"
#include "driver/AHT10.h"
os_timer_t soft_timer1;//software_timer_structure
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
void soft_timer1_cb(void){
AHT10_Read_Data();
}
void ICACHE_FLASH_ATTR
user_init(void)
{
i2c_master_gpio_init();
AHT10_Init();
os_timer_disarm(&soft_timer1);
os_timer_setfn(&soft_timer1,(os_timer_func_t *)soft_timer1_cb,NULL);
os_timer_arm(&soft_timer1,2000,1);
}