ESP32调库修炼指南
git
参考资料
- git下载地址:Git - Downloads (git-scm.com)
- git官方wiki:Git - Reference (git-scm.com)
- 参考教程:廖雪峰的官方网站 (liaoxuefeng.com)|菜鸟教程 (runoob.com)
应用场景
- 版本控制和记录
- 分支处理
- buff:配合github/gitee/gitlab进行线上协作
基本用法
仓库的获取、创建
git clone address
git init
仓库的下载、建立初始仓库
文件
git add ./某个文件(夹)
添加文件到暂存区
git commit -m "string"
git tag -a "v3.14"
git log
git stash
git stash drop
将暂存区内容添加到仓库中、查看commit记录
如何废弃放进暂存区的修改(用于和线上同步)
分支
git branch (branchname)
git checkout (branchname)
git merge
创建分支、切换分支、合并分支*
线上
git pull
git push
下载、上传远程代码并合并
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
账号管理(私人仓库)
ESP32
参考资料
- 官网首页:提供 Wi-Fi、蓝牙芯片和 AIoT 解决方案 I 乐鑫科技 (espressif.com)
- 编程指南:快速入门 - ESP32-S2 - — ESP-IDF 编程指南 v4.4.1 文档 (espressif.com)
- github:espressif/esp-idf: Espressif IoT Development Framework. Official development framework for Espressif SoCs. (github.com)
- 论坛:ESP32 Forum - 首页
单片机特点(暴论)
ESP32相较于STM32还是有很多独特之处的:
- 首先,ESP32借助的是外部SPI Flash,则意味着内部可能自带了一个bootloader;
- 其次,ESP32刻意回避了裸机开发,通过抽象到arduino/micropython/ESP-IDF等强调软件;
- 因为套了太多层,ESP32至少在vscode插件里没有做调试,但是在硬件错误的时候可以查到来源,还算好解决问题。
- ESP32内部的芯片外设具有IO MUX,在编程的时候任意引脚(系统及其存储除外)都可以更换;
- 另外,ESP32的外设是软件方式+硬件方式相结合,比较明显的硬件外设是SPI,其他的尚不清楚;
- 乐鑫公司自家的开发方式ESP-IDF是个究极融合怪,里面包含了很多开源的东西,例如FreeRTOS。
应用场景
- IoT
- 高性能、外设数量少的单片机应用
- micropython/arduino
VS code 插件
学会打开文件夹很重要!
API
应用程序接口(API,Application Programming Interface)简单来说抽象的代码库。简单来说,就是上游的工程师给我们这些单片机半吊子码农写了一套单片机的编程流程。
常规的单片机开发流程(不采用寄存器驱动),一般分几步:
- 一个外设初始化结构体和初始化结构体的初始化函数
- 在初始化结构体里设置参数
- 一个外设结构体(句柄)和句柄通过初始化结构体的初始化函数
单片机开发其实受限于这些API,这些软件设计的BUG(某个红色标记的大厂商)、优劣势都会影响单片机功能和性能的发挥,间接影响单片机的流行度和销量。
ESP-IDF注意事项
- freeRTOS和event
ESP_LOGI
的使用
freeRTOS
参考资料
官网:FreeRTOS - Market leading RTOS for embedded systems with Internet of Things extensions
基本操作
任务的创建
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为4字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask //任务句柄, 用于操作这个任务
);
任务的删除
void vTaskDelete( TaskHandle_t xTaskToDelete );
用途实例:
函数实例 | 实际用途 |
---|---|
vTaskDelete(NULL) | 删除自己这个任务 |
vTaskDelete(pvTaskCode) | 删除某个其他任务 |
任务的延时
/* xTicksToDelay: 等待的周期
*/
void vTaskDelay( const TickType_t xTicksToDelay );
/* pxPreviousWakeTime: 上一次被唤醒的时间
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime + xTimeIncrement)
* 单位都是Tick Count
*/
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement );
任务的延时其实非常重要,只有在任务里延时,其他被阻塞的(blocked)任务才有机会运行。
注:在STM32里面的HAL_Delay()
在RTOS里就不要用了,这东西是SysTick实现的,依然对其他任务无效。
调度算法
非运行状态的任务,它处于这3种状态之一:阻塞(Blocked)、暂停(Suspended)、就绪(Ready)。就绪态的任务,可以被调度器挑选出来切换为运行状态,调度器永远都是挑选最高优先级的就绪态任务并让它进入运行状态。
阻塞状态的任务,它在等待"事件",当事件发生时任务就会进入就绪状态。事件分为两类:时间相关的事件、同步事件。所谓时间相关的事件,就是设置超时时间:在指定时间内阻塞,时间到了就进入就绪状态。使用时间相关的事件,可以实现周期性的功能、可以实现超时功能。同步事件就是:某个任务在等待某些信息,别的任务或者中断服务程序会给它发送信息。怎么"发送信息"?方法很多,有:**任务通知(task notification)、队列(queue)、事件组(event group)、信号量(semaphore)、互斥量(mutex)**等。这些方法用来发送同步信息,比如表示某个外设得到了数据。
调度算法的行为主要体现在两方面:高优先级的任务先运行、同优先级的就绪态任务如何被选中。调度算法要确保同优先级的就绪态任务,能“轮流”运行,策略是“轮转调度”(Round Robin Scheduling)。轮转调度并不保证任务的运行时间是公平分配的,我们还可以细化时间的分配方法。
两项宏设置
USE_PREEMPTION
:抢占,启用“可抢占调度”(Pre-emptive),高优先级的就绪任务马上进行;不启用则为"合作调度模式"(Co-operative Scheduling),高优先级的就绪任务需要等待运行的任务主动让出资源。USE_TIME_SLICING
:时间片,同优先级的任务轮流执行。
LVGL
参考资料
- 官网:LVGL - Light and Versatile Embedded Graphics Library
- 文档:Welcome to the documentation of LVGL! — LVGL documentation
- github(团队域名,在里面可以找到一些指南和PC模拟器):LVGL (github.com)
- 代码生成器(类似于qt designer/cubeMX,收费):SquareLine Studio
移植指南
屏幕移植难度取决于屏幕。
输入设备:触摸屏、键盘(真的键盘)、按键(lvgl认为是补充)、编码器