Esp32串口自动下载电路,嵌入式开胃菜,你学废了么
芯片程序下载的特定状态
芯片上电都是直接执行用户程序的。 要想进行程序更新,就必须进入特定的串口下载状态。 Esp32 就是要求goio0拉低, 然后启动。 这样就进入了下载状态。
串口更新程序,是最通用的方式。但是启用这个模式大概率都需要在复位前,配置某一个或者某几个引脚。 然后复位或者要求重新上电。 这样就进入了下载状态。
串口自动下载电路
嵌入式工程师都会复用现有的资源去实现新的功能。 这个串口自动下载电路,就是这样的一个例子。cp210x是有扩展的gpio口的。但是用起来就比较特例。当然, 如果通用串口的一些引脚能够复用,那应该是更好的事情。但是, 因为功能已经被定义了。所以,需要一些辅助电路进行兼容。防止引入新的问题。
这个图来自我买的esp32-s3的小板, chip_pu 是reset, gpio0是boot。 他pdf上的真值表是错的。 我就不贴出来了。 两个三极管都是npn,只是为了好画图镜像了一下。 可没有锁存器那么复杂。
这里把两个引脚的其他电路也贴出来。 因为如果仅仅是简单逻辑,可能就不会迷糊了那么多人。 因为三极管电路是一个数字电路。 这个纯数字电路实现不了复位下载要求的时序。
真值表分析:
DTR | CTS | chip_pu | gpio0 | 原因 |
---|---|---|---|---|
1 | 1 | x | x | be之间没有电压差,没有电流。三极管关掉。不影响当前状态 |
0 | 0 | x | x | be之间没有电压差,没有电流。三极管关掉。不影响当前状态 |
1 | 0 | 0 | x | chip_pu被拉低. gpio0 三极管关断 |
0 | 1 | x | 0 | chip_pu三极管关断. gpio0 三极管打开,拉低 |
因为引脚上都有默认上拉电阻。所以x一般被认为1. 除非开关按下,强制为0
class ClassicReset(ResetStrategy):
"""
Classic reset sequence, sets DTR and RTS lines sequentially.
"""
def reset(self):
self._setDTR(False) # IO0=HIGH
self._setRTS(True) # EN=LOW, chip in reset
time.sleep(0.1)
self._setDTR(True) # IO0=LOW
self._setRTS(False) # EN=HIGH, chip out of reset
time.sleep(self.reset_delay)
self._setDTR(False) # IO0=HIGH, done
我们要把软件代码和硬件信号对齐。 这里DTR都是低有效。 所以代码里设置为true,就是拉低。 代码里设置为false,就是拉高。 嵌入式不难,但是细节多。这些看起来让人迷糊的细节,又是规范,再牛逼的人也改不了。 互联网行业喜欢造规范,但是这些迷惑人的东西,才是真正的规范。
前两句设置复位状态。然后等待0.1s, 这个等待是把复位电容里的电放光(快)。io0的电容充电到满(慢),芯片复位状态cpu是停止的。 然后设置io0为低电平。复位结束,cpu开始运行, 这时候cpu检测到io0为低电平,就进入下载状态。 注意三极管放电速度,大于电容上拉充电速度。 也就是说控制电路只保证了io0是低电平, 复位引脚是类似开漏控制, 也可以认为控制电路未连接 复位引脚自然执行的是电阻给电容充电,缓慢上升和复位结束。
最后, 把io0恢复到不控制状态。 这样就可以正常运行了。因为io0还可以有其他功能。 一直拉低就浪费了这个引脚。
总结
- 如果驱动注册的是modem,这个下载永远是不会成功的。 因为modem使用了这两个控制引脚。我的macos就是这么一直不成功,浪费了我一天。重装ch34x驱动以后, 驱动又注册了一个串口, 可以下载了。
- 如果io0输出低, 按键复位的时候, 要保证结束时io0是高电平,否则之间进入boot模式了。
- 和不经过三极管直接控制电路相比, 稳定性有提高,防止串口输出信号和cpu引脚,复位按键同时输出导致的打架。
- 但是是否真需要这么复杂, 是解决哪些历史设计不兼容,已经无从考证了。就算是一个前辈秀技术,也成了祖传逻辑。当然,很多简化的电路。也能正常运行。