借助claude code解决 逐飞库STC32G144K 上 WiFi SPI 与 MT9V03X 摄像头共用时,示波器数据震荡问题。
根因:逐飞库exit_init(INT1_P33, BOTH)的BOTH在 8051 上是电平触发(IT1=0)。VSYNC 低电平期间 INT1 每个时钟周期都触发,IE1 不断被硬件置位,与 SPI DMA 的寄存器轮询产生 SFR 总线竞争,导致数据错乱。
解决:发送 WiFi 数据时临时EX1=0关中断,发完EX1=1恢复。仅影响发送的几毫秒,不影响摄像头和图像处理
省流:
在 SPI DMA 轮询的几毫秒内屏蔽 INT1,发完立刻恢复
一.摄像头与wifi发送波形信号分开写
结果:波形在目标值和0直接反复横跳
如图
二.注释摄像头初始化函数
结果:得到平滑波形
问题在摄像头某处与wifi冲突
三.参考逐飞摄像头wifi图传
得到平滑波形
四.加上图像处理
结果:震荡
深入底层:
在exit_init(INT1_P33, BOTH)这个函数调用上。
逐飞库的外部中断初始化函数exit_init中,BOTH枚举值为 0:
typedef enum { BOTH, // = 0 FALLING_EDGE, // = 1 } INT_MODE_enum; void exit_init(INTN_enum int_n, INT_MODE_enum mode) { IT1 = mode; // BOTH=0 → IT1=0 EX1 = 1; }在 8051 架构上,IT1=0意味着电平触发,而非"双边沿触发"(8051 根本没有双边沿模式)。MT9V03X 摄像头的 VSYNC 信号接在 P3.3(INT1),时序如下:
- VSYNC 高电平:帧间空闲期(~2ms)
- VSYNC 低电平:帧读出期(~18ms)
当 VSYNC 为低电平时,由于是电平触发,INT1 中断每个机器周期都在触发,硬件不断置位 IE1 标志位。
与此同时,WiFi SPI 模块通过 SPI2 DMA 发送数据,底层实现是轮询 DMA 状态寄存器:
DMA_SPIX_CR(spi_n) = 0xC1; // 启动DMA while(!(DMA_SPIX_STA(spi_n) & 0x01)); // 轮询等待完成 ← 这里被干扰当 INT1 持续触发时,IE1 标志位不断被硬件写入,与 SPI DMA 的寄存器轮询产生SFR 总线竞争,导致读到错误的 DMA 状态值,数据传输错乱 → 示波器波形震荡。
有无图像处理结果不同分析:
情况一:不加图像处理 —— 好使
没有图像处理时,主循环跑得很快:
摄像头拍完 → 收到flag → 发WiFi → 回到循环顶部 → 等下一帧拍完 → 再发...每帧只花几微秒发 WiFi,然后就回到循环顶部等着。发 WiFi 的时候,VSYNC 是高电平(帧间空闲期),中断不会疯狂触发,所以数据传输正常,波形平滑。
情况二:加上图像处理 —— 震荡
加上图像处理后,主循环变慢了:
摄像头拍完 → 收到flag → 发WiFi → 图像处理(耗时20ms以上!)→ 回到循环顶部图像处理要 20 多毫秒,而摄像头一帧 10ms。也就是说,图像处理还没做完,下一帧就已经拍完了。
当图像处理结束回到循环顶部时,flag 已经被新帧置位了,程序立刻又进入发送流程。但这时候摄像头正在读出新帧,VSYNC 是低电平。
低电平 + 电平触发 = 中断每个时钟周期都在疯狂触发。
最终解决:
在 SPI DMA 轮询的几毫秒内屏蔽 INT1,发完立刻恢复
—— ——由claude(mimo-2.5-pro)激情解答,本次token消耗,1亿。嘤嘤嘤
不一定正确,仅供参考