文是关于 ESP32 - ULP 协处理器在低功耗模式下模拟 I2C 主机读取光照传感器 BH1750 的例子
1. I2C 管脚分配软件模拟 I2C 的例子使用 RTC_GPIO9, RTC_GPIO8 两个管脚, 对应的 GPIO 管脚如下表 I2C_PINRTC_GPIOGPIO
I2C_SCLRTC_GPIO9GPIO32
I2C_SDARTC_GPIO8GPIO33
2.软件环境配置
ESP32 的 C 语言编译环境安装和配置参照 链接地址,另外 ULP 协处理器目前只支持汇编编程,所以还需要安装汇编工具链,下面介绍汇编工具链的安装和配置。
2.1 汇编环境的配置
ULP 协处理器配置汇编编译工具链,只需两步即可安装配置完毕,下面给出 ubuntu 操作系统下配置的步骤,或者点击 链接地址 获得更多 ULP 编程信息
第一步, 下载工具链 binutils-esp32ulp toolchain 链接地址, 解压到需要安装的目录
第二步,添加工具链的 bin 目录到系统环境变量 PATH 中。例如我的解压目录是 /opt/esp32ulp-elf-binutils 那么添加 export PATH=/opt/esp32ulp-elf-binutils/binPATH 这一行到 /home 目录的隐藏文件 .bashrc 文件最后一行,保存关闭文件并使用命令 source .bashrc 使上述环境变量生效
2.2 配置编译烧录至此,汇编编译环境就安装好了,在 ulp_i2c_bitbang/ 目录下依次运行以下命令,进行 default config 配置并编译、烧录程序。 - make defconfig
- make all -j8 && make flash monitor
[color=rgba(0, 0, 0, 0.501960784313726)]
3. stack.S 堆栈宏说明
由于当前 ULP 协处理器汇编环境没有实现关于子函数的调用和返回堆栈保存等操作,需要用户来实现和构造这部分。所以在四个通用寄存器中我们牺牲 R3 寄存器用来当做栈指针,实现了 4 个关于堆栈操作的宏 PUSH、POP、PSR、RET,以上的宏在 stack.S 汇编文件中。
1. push,这个操作是把 Rx(R0,R1,R2)的数据压到 R3 所指向的栈里,栈指针向下增长
- .macro push rx
- st \rx,r3,0
- sub r3,r3,1
- .endm
复制代码 2.pop,把 R3 所指向的栈里的数据保存到 Rx(R0,R1,R2)中,栈指针回退
- .macro pop rx
- add r3,r3,1
- ld \rx,r3,0
- .endm
复制代码 3.psr,这个宏是计算出函数执行完毕后需要返回的地址,将其保存到栈上,即当前地址加上偏移 16 就是子函数跳转执行完毕后需要返回的地址
- .macro psr
- .set addr, (.+16)
- move r1, addr
- push r1
- .endm
复制代码 4.ret,此宏是把栈上保存的返回地址取出来,然后跳转到这个地址
- .macro ret
- pop r1
- jump r1
- .endm
复制代码
4. i2c.S 汇编函数说明
5. i2c_dev.S 汇编函数
6. 读取光照传感器I2C 设置 BH1750 的时序如下
I2C 测量 BH1750 的光照结果,时序如下
ULP 协处理器通过软件模拟 I2C 读取 BH1750 的光照强度打印在如下图中,通过遮挡传感器的光栅窗口可获得不同的光照数值。
7. 总结我们构造了 4 个用于堆栈管理的宏,我们可以方便的进行函数跳转和函数返回,软件模拟 I2C 比硬件指令 I2C 更为灵活,可以实现更为大型和复杂的 ESP32 低功耗应用。 作者 espressif 来源 CSDN
|