坚持走自己路 發表於 2025-9-8 00:00:00

10倍效率读代码!AI神器助你秒懂任何陌生项目(保姆级教程)

<h1 id="第三课-如何使用-ai-工具辅助快速阅读陌生代码">第三课 如何使用 AI 工具辅助快速阅读陌生代码</h1>
<h1 id="摘要"><strong>摘要:</strong></h1>
<p>本文以MicroPython红外传感器驱动为例,3步搞定代码阅读,快速上手新模块开发。<br>
对于新手而言,首次阅读陌生代码比较困难,看不懂写的是什么、如何进行测试?都是常见的问题。</p>
<p>接下来,我们以 MicroPython 版本的红外收发模块驱动代码为例,讲解如何使用 AI 工具辅助快速阅读并理解陌生代码,以便未来能独立处理其他模块的代码。</p>
<p>与此同时,该文章也旨在教会新手使用 AI 工具来:</p>
<ul>
<li>降低学习新代码的成本和时间</li>
<li>理解 AI 辅助代码阅读的最佳实践</li>
<li>获得可复用的分析框架。</li>
</ul>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202503/2591203-20250321010016257-450656136.png"></p>
<blockquote>
<p><strong>关于我们更多介绍可以查看云文档:</strong>Freak 嵌入式工作室云文档<strong>,或者访问我们的 wiki:https://github.com/leezisheng/Doc/wik</strong></p>
</blockquote>
<h1 id="原文链接"><strong>原文链接:</strong></h1>
<p><strong>FreakStudio的博客</strong></p>
<h1 id="往期推荐"><strong>往期推荐:</strong></h1>
<p><strong>学嵌入式的你,还不会面向对象??!</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:00 面向对象设计方法导论</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:02 类和对象的 Python 实现-使用 Python 创建类</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:03 类和对象的 Python 实现-为自定义类添加属性</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:04 类和对象的Python实现-为自定义类添加方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:13 类和对象的Python实现-可视化阅读代码神器Sourcetrail的安装使用</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:20 类和对象的Python实现-组合关系的实现与CSV文件保存</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:21 类和对象的Python实现-多文件的组织:模块module和包package</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:22 类和对象的Python实现-异常和语法错误</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:23 类和对象的Python实现-抛出异常</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:24 类和对象的Python实现-异常的捕获与处理</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:26 类和对象的Python实现-上下文管理器和with语句</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规范大汇总</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:33 Python的内置数据类型-对象Object和类型Type的关系</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:45 Python实现常见数据结构-链表、树、哈希表、图和堆</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:48 Python函数方法与接口-位置参数、默认参数、可变参数和关键字参数</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:51 Python函数方法与接口-使用Zope实现接口</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:52 Python函数方法与接口-Protocol协议与接口</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:53 Python字符串与序列化-字符串与字符编码</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:57 Python字符串与序列化-序列化与反序列化</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现</strong></p>
<p><strong>全网最适合入门的面向对象编程教程:59 Python并行与并发-并行与并发和线程与进程</strong></p>
<p><strong>一文速通Python并行计算:00 并行计算的基本概念</strong></p>
<p><strong>一文速通Python并行计算:01 Python多线程编程-基本概念、切换流程、GIL锁机制和生产者与消费者模型</strong></p>
<p><strong>一文速通Python并行计算:02 Python多线程编程-threading模块、线程的创建和查询与守护线程</strong></p>
<p><strong>一文速通Python并行计算:03 Python多线程编程-多线程同步(上)—基于互斥锁、递归锁和信号量</strong></p>
<p><strong>一文速通Python并行计算:04 Python多线程编程-多线程同步(下)—基于条件变量、事件和屏障</strong></p>
<p><strong>一文速通Python并行计算:05 Python多线程编程-线程的定时运行</strong></p>
<p><strong>一文速通Python并行计算:06 Python多线程编程-基于队列进行通信</strong></p>
<p><strong>一文速通Python并行计算:07 Python多线程编程-线程池的使用和多线程的性能评估</strong></p>
<p><strong>一文速通Python并行计算:08 Python多进程编程-进程的创建命名、获取ID、守护进程的创建和终止进程</strong></p>
<p><strong>一文速通Python并行计算:09 Python多进程编程-进程之间的数据同步-基于互斥锁、递归锁、信号量、条件变量、事件和屏障</strong></p>
<p><strong>一文速通Python并行计算:10 Python多进程编程-进程之间的数据共享-基于共享内存和数据管理器</strong></p>
<p><strong>一文速通Python并行计算:11 Python多进程编程-进程之间的数据安全传输-基于队列和管道</strong></p>
<p><strong>一文速通Python并行计算:12 Python多进程编程-进程池Pool</strong></p>
<p><strong>一文速通Python并行计算:13 Python异步编程-基本概念与事件循环和回调机制</strong></p>
<p><strong>一文速通Python并行计算:14 Python异步编程-协程的管理和调度</strong></p>
<p><strong>一文速通 Python 并行计算:教程总结</strong></p>
<h1 id="更多精彩内容可看"><strong>更多精彩内容可看:</strong></h1>
<p><strong>C语言一点五编程实战:纯 C 的模块化×继承×多态框架</strong></p>
<p><strong>给你的 Python 加加速:一文速通 Python 并行计算</strong></p>
<p><strong>一文搞懂 CM3 单片机调试原理</strong></p>
<p><strong>肝了半个月,嵌入式技术栈大汇总出炉</strong></p>
<p><strong>电子计算机类比赛的“武林秘籍”</strong></p>
<p><strong>一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库</strong></p>
<p><strong>Avnet ZUBoard 1CG开发板—深度学习新选择</strong></p>
<p><strong>工程师不要迷信开源代码,还要注重基本功</strong></p>
<p><strong>什么?配色个性化的电机驱动模块?!!</strong></p>
<p><strong>什么?XIAO主控新出三款扩展板!</strong></p>
<p><strong>手把手教你实现Arduino发布第三方库</strong></p>
<p><strong>万字长文手把手教你实现MicroPython/Python发布第三方库</strong></p>
<p><strong>一文速通电子设计大赛,电子人必看的获奖秘籍</strong></p>
<p><strong>一文速通光电设计大赛,电子人必看!</strong></p>
<p><strong>工科比赛“无脑”操作指南:知识学习硬件选购→代码调试→报告撰写的保姆级路线图</strong></p>
<p><strong>单场会议拍摄收费6000+?拍摄技巧和步骤都在这里</strong></p>
<p><strong>0基础如何冲击大唐杯国奖?学姐的的备赛心得都在这里</strong></p>
<p><strong>爆肝整理长文】大学生竞赛速通指南:选题 × 组队 × 路演 48 小时备赛搞定</strong></p>
<p><strong>当代大学生竞赛乱象:从“内卷”到“祖传项目”的生存指南</strong></p>
<p><strong>女大学生摆摊亏损5000元踩点实录:成都哪里人最多、最容易赚到钱?我告诉你!</strong></p>
<p><strong>用拍立得在成都网红打卡点赚钱:一份超实用地摊级旅游副业教程</strong></p>
<p><strong>成都印象:一个电子女孩亲手做了点浪漫</strong></p>
<p><strong>普通继电器 vs 磁保持继电器 vs MOS管:工作原理与电路设计全解析</strong></p>
<p><strong>告别TP4056!国产SY3501D单芯片搞定充放电+升压,仅需7个元件!附开源PCB文件</strong></p>
<p><strong>POB面向老板编程—现实驱动的新型编程范式</strong></p>
<h1 id="正文">正文</h1>
<h1 id="零阅读代码的推荐方法">零、阅读代码的推荐方法</h1>
<h2 id="01-准备工作与工具选择">0.1 准备工作与工具选择</h2>
<ol>
<li>
<p>AI 工具选择:我们将使用大型语言模型(如 ChatGPT、Claude、DeepSeek-Coder、Kimi 等)作为核心辅助工具。它们能解释代码、翻译注释、生成示例,甚至推理逻辑。</p>
</li>
<li>
<p>目标代码:假设我们的目标是学习并使用一个陌生的驱动库来控制红外发射和接收。</p>
</li>
<li>
<p>知识管理工具:按照建议,飞书文档 是最佳选择。我们将在飞书中创建一个新文档,并按照推荐的目录结构进行整理。它的实时协作、代码块高亮、表格和流程图支持非常适合这个任务。</p>
</li>
<li>
<p>可视化代码阅读工具的安装与使用:Sourcetrail 是一款跨平台的开源代码可视化工具,它能自动解析代码结构,生成类、函数、文件之间的调用关系图,帮助我们快速理解陌生项目的框架:</p>
<ul>
<li><strong>可视化调用图</strong>:函数、类、模块的依赖关系一目了然。</li>
<li><strong>交互式跳转</strong>:点击图谱中的节点可直接查看对应源码。</li>
<li><strong>多语言支持</strong>:C/C++、Java、Python 等主流语言。</li>
<li><strong>跨平台</strong>:支持 Windows、macOS 和 Linux。</li>
</ul>
</li>
</ol>
<p>关于可视化代码阅读工具的安装与使用基本教程可以查看:</p>
<p>https://blog.csdn.net/weixin_44719294/article/details/140337899</p>
<h2 id="02-在飞书文档中建立分析框架">0.2 在飞书文档中建立分析框架</h2>
<h3 id="021-readme-文件阅读内容整理">0.2.1 README 文件阅读内容整理</h3>
<ul>
<li>模块的用途</li>
<li>硬件/软件依赖</li>
<li>安装方法</li>
<li>示例代码</li>
</ul>
<p>(AI 辅助用法:让 AI 总结 README 的重点,提取输入输出接口、调用方法等关键信息,避免遗漏。)</p>
<h3 id="022-代码文件关系组织整理">0.2.2 代码文件关系组织整理</h3>
<ul>
<li>每个 <code>.py</code> 文件的作用</li>
<li>主入口文件与子模块依赖关系</li>
<li>类与函数的大致调用链</li>
</ul>
<p>(AI 辅助用法:请 AI 绘制“模块调用关系图”或“依赖树”,比人工翻代码更高效。)</p>
<h3 id="023-代码功能具体实现分析">0.2.3 代码功能具体实现分析</h3>
<ul>
<li>每个类/函数的作用与参数</li>
<li>核心逻辑(如:如何接收/发射红外信号)</li>
<li>关键算法或协议实现(如 NEC、SONY、RC5 等)</li>
</ul>
<p>(AI 辅助用法:将函数贴给 AI,要求用“伪代码”或“流程图”形式解释逻辑,帮助快速理解代码意图。)</p>
<h3 id="024-应用时注意事项整理">0.2.4 应用时注意事项整理</h3>
<ul>
<li>代码运行环境要求(MCU 型号、固件版本)</li>
<li>常见错误与调试方式</li>
<li>使用 <code>uasyncio</code> 等异步框架时的注意点</li>
<li>协议支持与不支持的范围</li>
</ul>
<p>(AI 辅助用法:让 AI 生成“使用清单 + 注意事项表格”,新手只需对照即可上手。)</p>
<h2 id="03-学习与应用的最佳实践">0.3 学习与应用的最佳实践</h2>
<ol>
<li><strong>先结构化 → 再细节化</strong>:先搭建整体框架,再逐步深入。</li>
<li><strong>善用 AI 工具</strong>:AI 不是替你写笔记,而是帮你节省阅读和理解的时间。</li>
<li><strong>形成复用模板</strong>:以后遇到任何新模块,都可以套用“README → 文件关系 → 功能实现 → 应用注意”这套流程。</li>
</ol>
<h1 id="一阅读-readme-文件">一、阅读 README 文件</h1>
<h2 id="11-仓库简介总览">1.1 仓库简介总览</h2>
<p>首先,我们打开示例代码网址:https://github.com/peterhinch/micropython_ir</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234914705-652226779.png"></p>
<p>我们首先看右侧的仓库简介:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234918136-693369066.png"></p>
<p><strong>原句:</strong></p>
<blockquote>
<p>Nonblocking device drivers to receive from IR remotes and for IR "blaster" apps.</p>
</blockquote>
<p>翻成中文就是:</p>
<blockquote>
<p>“用于接收红外遥控器并用于红外‘发射器(blaster)’应用的非阻塞设备驱动程序。”</p>
</blockquote>
<p>这里,我们可以将该段话输入给 AI,并辅助说明:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234931704-732681640.png"></p>
<p>这里,对于新手来说,往往有许多基础知识缺乏,需要对 AI 明确指出,需要<strong>结合基础知识</strong>进行讲解:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234936584-1105674622.png"></p>
<p>以上,我们不难猜测到,该代码中可以分为协议层和物理实现层,即:</p>
<ul>
<li><strong>物理实现层:</strong>这一层负责直接与硬件打交道,它的核心任务是精确地捕获原始的物理信号,并将其转换成更易于处理的时间数据。它不关心这些数据代表什么含义,只负责“忠实记录”。</li>
<li><strong>协议层:</strong>这一层负责解读物理层提供的原始数据,根据特定的通信协议规则,将这些时间序列“翻译”成有实际意义的数字代码。它不关心信号是如何采集的,只关心“数据代表什么”。</li>
</ul>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234943040-808485043.png"></p>
<p>上面讲解了红外收发模块,发送和接收的基本软件实现思路和硬件原理。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234947852-1671644860.png"></p>
<p>以上,主要讲解了该代码在设计和应用时的注意事项。</p>
<h2 id="12-仓库总体-readme-文件解读">1.2 仓库总体 README 文件解读</h2>
<p>接下来,我们继续看仓库的 README 文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234953928-1267894131.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907234957891-1892606061.png"></p>
<p>老规矩,直接复制粘贴,喂给 AI,同时在最开始加上:<strong>对下面 进行详细解读结合基础知识</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235002686-28898798.png"></p>
<p>没有使用异步编程,猜测是使用中断 + 定时器进行替代,继续看:</p>
<h3 id="121-平台兼容性与固件版本须知">1.2.1 平台兼容性与固件版本须知</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235007463-1712318881.png"></p>
<p>这里,说明了该驱动库适合在哪些 MCU 上运行以及早期版本的 BUG 和解决方法。</p>
<h3 id="122-ir-通信基础知识">1.2.2 IR 通信基础知识</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235011520-1544122418.png"></p>
<p>这里是基础的通信原理知识。</p>
<h3 id="123-ir-协议相关">1.2.3 IR 协议相关</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235016144-1699373225.png"></p>
<p>这里,讲解了该代码支持哪些编码协议及其优缺点,如果进行测试的话,作者推荐首选 NEC 编码。</p>
<h3 id="124-ir-收发模块硬件需求讲解">1.2.4 IR 收发模块硬件需求讲解</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235021492-923803042.png"></p>
<p>这里是推荐的硬件,这个时候需要注意购买电子元器件/模块的具体参数。</p>
<h3 id="125-ir-载波协议支持载波频率">1.2.5 IR 载波协议支持载波频率</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235025100-360746319.png"></p>
<p>对于 38KHz 的接收头来说,只有三个协议支持,如果是笔者进行测试/简单应用,则只测试这三个协议。</p>
<h3 id="126-ir-接收注意事项">1.2.6 IR 接收注意事项</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235029848-402966225.png"></p>
<p>接收中断的注意事项和适配硬件,前文已经提到,简单跳过即可。</p>
<h3 id="127-应用细节与调试注意事项">1.2.7 应用细节与调试注意事项</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235034370-956744990.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235038021-1670802849.png"></p>
<p>以上为代码实现的注意事项,简单看过即可。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235041531-866473636.png"></p>
<p>这些是实际调试技巧,要额外记住,在测试代码时要回看该部分知识。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235045955-107323495.png"></p>
<p>这些是一些排除错误的方法,包括软件和硬件方面的,要额外记住,在测试代码时要回看该部分知识。</p>
<p>回到刚刚的网站,可以看到还有三个 README 文件我们没有查看:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235135513-1620246760.png"></p>
<h2 id="13-红外接收部分-readme-文件解读">1.3 红外接收部分 README 文件解读</h2>
<h3 id="131-快速浏览目录">1.3.1 快速浏览目录</h3>
<p>先打开 RECEIVER.md,根据名字我们不难推断这里是讲解红外接收部分代码的文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235140874-864444625.png"></p>
<p>快速概览,可以看到分成下面几个目录:</p>
<ul>
<li><strong>Hardware Requirements:</strong>一般这里讲解需要什么硬件、注意事项和使用的 MCU 型号与对应测试引脚。</li>
<li><strong>Installation and demo scripts:</strong>这里,一般描述如何把驱动安装到设备上并运行示例脚本。</li>
<li><strong>The driver:</strong>这里,主要讲解了类的设计思路。</li>
<li><strong>Errors:</strong>列举可能的错误类型与诊断建议。</li>
<li><strong>Receiver platforms:</strong>说明已测试与限制的平台。</li>
<li><strong>Principle of operation:</strong>用简短段落解释工作原理和如何快速使用驱动。</li>
<li><strong>Unsupported protocols:</strong>列出未支持或不可保证工作的协议并解释原因</li>
<li><strong>Use with uasyncio:</strong>说明与 uasyncio 的集成方式与建议实践。</li>
</ul>
<p>后面则是两个协议附录,这部分一般不需要详细了解:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235146301-581370829.png"></p>
<h3 id="132-硬件需求电平标准推荐接线与测试须知">1.3.2 硬件需求、电平标准、推荐接线与测试须知</h3>
<p>接下来,我们一段一段喂给 AI 即可:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235150046-1309913722.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235154128-604757584.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235159042-959981253.png"></p>
<h3 id="133-包的安装与测试">1.3.3 包的安装与测试</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235202945-1645284914.png"></p>
<p>这个是使用 mpremote 工具和 mip 库来安装包,也可以将代码下载下来进行烧录。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235208448-1652042091.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235212510-486686006.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235217582-1408746429.png"></p>
<h3 id="134-协议层的解读">1.3.4 协议层的解读</h3>
<p>在解读协议层时,我们可以看到有好几个协议,此时我们可以要求 AI 列表格对比:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235221514-2021001833.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235226101-179852239.png"></p>
<h3 id="134-代码架构解析">1.3.4 代码架构解析</h3>
<p>可以看到,几个协议都有共同的抽象基类,应该是通过类的继承实现的,三个协议类都有共同的公共方法:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235229883-458363112.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235234817-713326732.png"></p>
<h3 id="134-常见错误解析与输出">1.3.4 常见错误解析与输出</h3>
<p>下面是常见错误与解析:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235239027-2104209432.png"></p>
<p>可以看到类中还定义了一些错误常量,在调试时可以根据对应错误常量判断错误类型:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235243251-1106542677.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235246913-1496392757.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235250197-85674422.png"></p>
<p>上面讲解了,如何打印错误,在发生错误时可以通过该函数来打印错误类型到 REPL 中。</p>
<h3 id="135-特定平台上测试的不同结果">1.3.5 特定平台上测试的不同结果</h3>
<p>接下来到了已经测试的 MCU 平台和结果对比:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235254501-1946317889.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235258401-839961940.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235301512-1671311999.png"></p>
<h3 id="136-代码工作原理详细说明">1.3.6 代码工作原理详细说明</h3>
<p>下面是工作原理部分:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235306574-644438204.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235310053-320623422.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235313165-1129961220.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235316441-1028481215.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235320244-1203160449.png"></p>
<h3 id="137-不支持的协议如何处理">1.3.7 不支持的协议如何处理</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235324041-798566324.png"></p>
<h3 id="138-异步实现的建议和注意事项">1.3.8 异步实现的建议和注意事项</h3>
<p>接下来是异步的实现和注意事项:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235327217-2095471564.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235331965-1161624396.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235335675-1065813467.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235339402-930003246.png"></p>
<h2 id="14-红外发送部分-readme-文件解读">1.4 红外发送部分 README 文件解读</h2>
<p>接下来,我们来看 TRANSMITTER.md 文件,这部分讲解了红外发送代码:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235344999-1741692575.png"></p>
<p>可以看到,整体目录相似,接下来,我们只需要一段一段喂给 AI 即可:</p>
<h3 id="141-硬件需求引脚相关">1.4.1 硬件需求、引脚相关</h3>
<p>首先是引脚相关:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235350326-1927880859.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235353912-1954555126.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235358019-1205962459.png"></p>
<h3 id="142-依赖库的安装">1.4.2 依赖库的安装</h3>
<p>接着是安装依赖库:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235402129-1785171492.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235405837-1549192497.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235409366-348910410.png"></p>
<h3 id="143-协议层的解读">1.4.3 协议层的解读</h3>
<p>接下来就是协议层和物理层实现的思路讲解,<strong>老规矩,列表格!</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235414022-1484788982.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235417656-740272147.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235422648-1554928973.png"></p>
<h3 id="144-工作原理讲解">1.4.4 工作原理讲解</h3>
<p>接着就是工作原理的具体讲解:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235426786-1404763954.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235429971-1953413448.png"></p>
<h3 id="145-不支持的协议如何处理">1.4.5 不支持的协议如何处理</h3>
<p>接下来就是对不支持的协议说明和对应解决方法了:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235434513-691491104.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235438178-517759451.png"></p>
<h2 id="15-特定平台实现的-readme-文件解读rp2040-pio">1.5 特定平台实现的 README 文件解读(RP2040-PIO)</h2>
<p>接下来,是 RP2_RMT.md 文件,这部分应该是对 PIO 汇编实现思路的基本讲解,直接喂给 AI 即可,考虑到我们的目的就是快速应用,这部分简略观看即可:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235444929-1028415972.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235448042-240693833.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235451622-711886483.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235456276-1162348292.png"></p>
<h1 id="二代码文件结构与关系梳理">二、代码文件结构与关系梳理</h1>
<h2 id="21-sourcetrail-软件的安装与使用">2.1 Sourcetrail 软件的安装与使用</h2>
<p>这里,我们首先需要下载安装 Sourcetrail 软件,具体安装和使用教程可以查看:</p>
<p>https://blog.csdn.net/weixin_44719294/article/details/140337899</p>
<p>接着,我们需要下载源代码:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235517103-2001765554.png"></p>
<h2 id="22-红外接收部分代码分析">2.2 红外接收部分代码分析</h2>
<h3 id="221-使用-sourcetrail-软件新建分析工程">2.2.1 使用 Sourcetrail 软件新建分析工程</h3>
<p>使用 <code>Sourcetrail</code> 软件打开,这里,我们首先分析接收部分代码:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235521366-1880981305.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235524514-1741801847.png"></p>
<p>接着添加 <code>G:\micropython_ir-master\ir_rx</code> 文件夹下代码文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235528485-1187702249.png"></p>
<p>注意,此时务必勾选最下面的选项,开始生成:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235533215-1172121990.png"></p>
<p>现在生成了分析结果:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235538971-578290894.png"></p>
<p>点击文件可以看到,总共有 8 个文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235542856-1349221626.png"></p>
<h3 id="222-文件作用说明">2.2.2 文件作用说明</h3>
<p>根据上面红外接收部分 README 文件解读结果,你可以使用 AI 生成一个无序表格,总结各个文件作用,但是此时一定要注意对照是不是正确:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235547812-1136080787.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235551058-211232095.png"></p>
<h3 id="223-代码文件与类的组织关系">2.2.3 代码文件与类的组织关系</h3>
<p>接下来,我们一个文件一个文件进行查看,首先点开初始化文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235555267-285655206.png"></p>
<p>其中,蓝色方框代表属性、黄色为类的方法,注意,这里我们只是应用该代码,所以直接输入给 AI,让 AI 总结每个方法的入口参数、返回参数和作用:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235600436-1400219910.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235605817-1977542373.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235610675-672086229.png"></p>
<p>依据上面 <strong>1.3.4 代码架构解析</strong> 总结的内容,该类为抽象基类,其余各个协议类继承于 <code>IR_RX</code> 类,我们一路返回到 <code>overview</code> 页面,点击 <code>Classes</code>:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235615865-1937401430.png"></p>
<p>然后点击 <code>IR_RX</code> 类</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235620108-25968800.png"></p>
<p>可以看到,有六个类都继承于 <code>IR_RX</code> 类,六个类都是不同协议的具体实现,除了父类的方法外,都有各自不同的 <code>decode</code> 解码方法以及其他一些内置属性和方法:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235625182-1095274558.png"></p>
<p>点开 <code>RC5_IR</code> 类,可以看到它在 <code>philips.py</code> 文件下面:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235629229-420099116.png"></p>
<p>打开浏览器的代码页面,<code>philips.py</code> 文件有两个类:<code>RC6_M0</code> 类和 <code>RC5_IR</code> 类,结合前面 <strong>1.2.3 IR 协议相关</strong>中内容,二者关系不难理解:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235636256-638501477.png"></p>
<p>这里,由于我们侧重于快速应用,因此 decode 编码方法的具体实现与原理可以略过。</p>
<p>类似地,<code>mce.py</code>、<code>nec.py</code>、<code>sony.py</code> 显然类似都是这样的情况:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235646715-1456786414.png"></p>
<p>根据前面的提示,我们知道了 <code> ir_rx/acquire.py</code> 文件是在红外协议未知时,用于捕获一个数据帧进行分析,结果需要人工判断,应该是使用里面的 <code>IR_GET</code> 类:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235653428-1523245234.png"></p>
<p>接着,我们继续查看其他文件,<code>ir_rx/print_error.py</code> 中声明了一个错误类型的字典和打印错误的函数,可以使用 <code>print_error</code> 函数打印错误类型和错误提示信息:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235700682-1163003081.png"></p>
<p>接着,就是 <code>ir_rx/test.py</code> 文件,根据名字不难判断,其中为测试文件:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235705425-299925631.png"></p>
<h2 id="23-红外发射部分代码分析">2.3 红外发射部分代码分析</h2>
<h3 id="231-使用-sourcetrail-软件新建分析工程">2.3.1 使用 Sourcetrail 软件新建分析工程</h3>
<p>主要流程同上,新建一个 <code>micropython_ir_tx</code> 分析工程:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235709709-253242016.png"></p>
<h3 id="232-文件作用说明">2.3.2 文件作用说明</h3>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235712743-659535618.png"></p>
<p>仍然是喂给 AI:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235717516-288847521.png"></p>
<h3 id="233-代码文件与类的组织关系">2.3.3 代码文件与类的组织关系</h3>
<p>首先打开 <code>ir_tx/__init__.py</code> 文件,可以看到里面有两个类:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235721776-17823874.png"></p>
<p>根据前文内容可以知道:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235725944-164503613.png"></p>
<p>IR 类主要用于脉冲序列生成和触发后台发送;Player 类继承自 IR 类,提供一种最小化的“波形直接播放”能力,常用于“录制-回放”场景(acquire 捕获后用 Player 回放)。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235730355-912191776.png"></p>
<p>其他的几个在 <code>ir_tx/mce.py</code>、<code>ir_tx/nec.py</code>、<code>ir_tx/philips.py</code> 和 <code>ir_tx/sony.py</code> 文件中不同协议具体实现的类,都继承于 IR 类,各自都有其实现的 tx 发送方法:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235734317-840401410.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235737916-1355325459.png"></p>
<p>对于 RP2040 上实现协议发送的特定 <code>ir_tx/rp2_rmt.py</code> 文件来说,在 <code>ir_tx/__init__.py</code> 文件中被导入:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235742988-1039063544.png"></p>
<p>对于 MCE 而言,还有一个特定测试文件 <code>ir_tx/mce.py</code>:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235746732-1039502489.png"></p>
<p>需要配合按键进行测试。</p>
<p>在通用的 ir_tx/test.py 文件中,可以看也添加了异步支持。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235751140-576918146.png"></p>
<h1 id="三代码功能具体实现分析">三、代码功能具体实现分析</h1>
<p>这里,只需要使用 AI 一个文件一个文件分析即可,以 ir_rx/nec.py 文件为例,在粘贴复制的文件前,在 AI 前面加入:</p>
<p><strong>说明以下代码中每个方法的工作原理和详细解读 结合基础知识:</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235756262-837387262.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235800174-1877929036.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235803289-928446937.png"></p>
<p>依次在文件中进行即可。</p>
<h1 id="四应用时注意事项整理">四、应用时注意事项整理</h1>
<p>以红外收发驱动代码为例,在了解了每个方法的实现原理和代码文件组织后,我们最核心的任务就是将驱动库利用起来,显然,最常见的使用 NEC 编码即可实现大部分功能,因此我们刚开始应用时仅需要研究如何使用红外收发模块发送和接收 NEC 编码,实现这个目的包括哪些文件需要去掉、哪些文件、需要新增哪些文件 (测试代码在 main.py)。</p>
<p>即<strong>尽快把驱动库裁剪成一个可用的、占用最小内存的工程,能接收 NEC 并发射 NEC(用于大多数家电遥控场景)</strong>。</p>
<p>我们询问 AI 即可,其实,经过 <strong>代码文件结构和关系梳理章节</strong>** **,我们已经了解到 各自协议类(发送和接收)其实都继承于 <code>__init__.py</code> 文件中的基类,因此该文件必须保留,同时还要保留各自协议类(发送和接收)对应的 py 文件,以及在特定平台上的功能文件。</p>
<p>建议的工程结构为:</p>
<pre><code class="language-python">irtranslation/
├─ ir_rx/                # 保留:接收端包(只复制需要的文件)
│├─ __init__.py
│├─ nec.py             # 必需(NEC 解码)
│├─ print_error.py   # 建议保留(调试用)
│└─ acquire.py         # 可选(用于嗅探/回放,不必要可删除)

├─ ir_tx/                # 保留:发射端包(只复制需要的文件)
│├─ __init__.py
│├─ nec.py             # 必需(NEC 发送)
│└─ rp2_rmt.py         # 如果用 Pico,则保留;否则可删

├─ main.py               # 新增:应用主程序(接收 + 发射/测试)
├─ README.md             # 说明文件
</code></pre>
<ul>
<li><strong>只导入 NEC</strong>:MicroPython RAM 宝贵,按需导入 <code>nec.py</code>,不要一次性 import 整个包内所有协议。</li>
<li><strong>删除/忽略</strong>:与 NEC 无关的协议文件(<code>sony.py</code>、<code>philips.py</code>、<code>mce.py</code>、<code>mcetest.py</code>、<code>test.py</code>(通用示例)等)在设备上可不拷贝,以节省空间。</li>
<li><strong>保留 ****print_error.py</strong>:便于将错误码打印为可读信息,调试时极有帮助。</li>
<li><strong>保留 ****rp2_rmt.py</strong>:如果目标是 Pico(RP2),必须保留用于 PIO 输出;ESP32 则靠 RMT,不需要 rp2 文件。</li>
</ul>
<p>接下来,我们首先将驱动库中 ir_rx 文件夹下 <code>nec.py</code>、<code>print_error.py</code> 和 <code>__init__.py</code> 文件原封不动输入给 AI:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235814134-2040633437.png"></p>
<p>接着输入一段话:</p>
<p><strong>如何使用<strong><strong>NEC_8</strong></strong>类,接收一段红外信号,同时需要考虑错误发生的情况</strong></p>
<p>可以看到输出了可以使用的示例:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235817916-2133303912.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235821478-2098388459.png"></p>
<pre><code class="language-python">from machine import Pin
from nec import NEC_8
from print_error import print_error

# 用户回调函数:收到数据后会被 NEC_8 调用
def ir_callback(cmd, addr, ext):
    if cmd &gt;= 0:
      # 正常解码成功
      print("✅ 收到按键: 地址 =", hex(addr), "命令 =", hex(cmd))
    else:
      # 出现错误或重复码
      print_error(cmd)

# 初始化 NEC_8 解码器
ir = NEC_8(Pin(16, Pin.IN), ir_callback)

print("红外接收已启动,按下遥控器按键测试...")
</code></pre>
<p>对于红外发射部分来说,继续上面的流程:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235828009-1937425580.png"></p>
<p>同时如果使用树莓派 Pico,还需要将 <code>ir_tx/rp2_rmt.py</code> 文件输入到 AI 中去:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235831412-1197749308.png"></p>
<p>接下来,输入测试平台(树莓派 Pico)、测试文件目录组织和具体要求:</p>
<blockquote>
<p><strong>在树莓派 Pico 上 测试 NEC_8 类,发送和接收一段红外信号,同时需要考虑错误发生的情况</strong><br>
<strong>代码文件目录组织如下:</strong><br>
<strong>project/</strong><br>
<strong>├─ ir_rx/                # 保留:接收端包(只复制需要的文件)</strong><br>
<strong>│├─ <strong>init</strong>.py</strong><br>
<strong>│├─ nec.py             # 必需(NEC 解码)</strong><br>
<strong>│├─ print_error.py   # 建议保留(调试用)</strong><br>
<strong>│└─ acquire.py         # 可选(用于嗅探/回放,不必要可删除)</strong><br>
<strong>│</strong><br>
<strong>├─ ir_tx/                # 保留:发射端包(只复制需要的文件)</strong><br>
<strong>│├─ <strong>init</strong>.py</strong><br>
<strong>│├─ nec.py             # 必需(NEC 发送)</strong><br>
<strong>│└─ rp2_rmt.py         # 如果用 Pico,则保留;否则可删</strong><br>
<strong>│</strong><br>
<strong>├─ main.py               # 新增:应用主程序(接收 + 发射/测试)</strong><br>
<strong>├─ README.md             # 说明文件</strong></p>
</blockquote>
<p>并点击思考时间更长:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235837627-279538891.png"></p>
<p>根据 AI 输出的代码和信息,按照规范测试即可:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235840962-2115403068.png"></p>
<pre><code class="language-python"># main.py
# Raspberry Pi Pico 测试 NEC 发射 + 接收 示例
# 同时处理错误码(使用 ir_rx.print_error)和 repeat 行为
#
# 说明:
# - 将红外发射 LED 连接到 TX_PIN(建议通过 NPN 或 MOSFET 驱动)
# - 将红外接收模块 OUT 引脚连接到 RX_PIN
# - 也会闪烁板载 LED(GP25)来指示接收到有效命令或 repeat

from machine import Pin
from time import sleep_ms, ticks_ms

# 接收端与错误打印
from ir_rx.nec import NEC_8
from ir_rx.print_error import print_error
from ir_rx import IR_RX# 用于引用 REPEAT 常量等

# 发射端
from ir_tx.nec import NEC as NEC_TX

# === 用户可配置项 ===
TX_PIN = 15      # 红外 LED 驱动管脚(GPIO15)
RX_PIN = 16      # 红外接收器 OUT 管脚(GPIO16)
ONBOARD_LED = 25 # Pico 板载 LED 管脚

# 如果你只有一块板并希望自行发射并同时接收(把 LED 对着接收头),设置为 True
LOOPBACK_TEST = True

# 测试要发送的 NE C地址/命令
TEST_ADDR = 0x10
TEST_DATA = 0x45
SEND_INTERVAL_MS = 3000# 每次发射间隔

# 是否在接收有效 command 时保存其为“最近有效”
KEEP_LAST_ON_VALID = True

# ========================


led = Pin(ONBOARD_LED, Pin.OUT)
# 发射器(NEC 发射类)
tx = NEC_TX(Pin(TX_PIN, Pin.OUT), freq=38000, verbose=False)

# 全局状态,保存最近一次有效命令以便处理 REPEAT
state = {
    'last_cmd': None,
    'last_addr': None,
    'last_time': 0# ms ticks
}

def handle_action(addr, cmd):
    """
    根据接收到的 (addr, cmd) 执行示例动作。
    在这里仅通过板载 LED 快闪做示范(你可以替换为具体业务逻辑)。
    """
    print("&gt;&gt;&gt; 执行动作: addr=0x{:02x}, cmd=0x{:02x}".format(addr, cmd))
    # 快闪 LED 表示收到命令
    led.value(1)
    sleep_ms(120)
    led.value(0)

def handle_repeat():
    """
    处理长按重复(REPEAT)逻辑:
    - 如果之前有记录的 last_cmd,将其视为长按并重复执行动作(示例中每次闪烁)
    - 否则打印提示
    """
    if state['last_cmd'] is None:
      print("收到 REPEAT,但没有上一次有效命令。忽略。")
      return
    print("收到 REPEAT(长按),重复上一次命令 addr=0x{:02x} cmd=0x{:02x}".format(
      state['last_addr'], state['last_cmd']))
    # 示例:每次 repeat 只做一次动作(你也可以用循环连续加速等)
    handle_action(state['last_addr'], state['last_cmd'])


def ir_rx_callback(cmd, addr, ext):
    """
    接收器回调(由 NEC_8 在解码后调用)
    - cmd &gt;= 0: 有效按键
    - cmd &lt; 0: 错误或 REPEAT(用 print_error 打印)
    """
    # cmd 为整数,成功时是非负命令值;错误/特殊值为 IR_RX.* 常量(负数)
    if cmd &gt;= 0:
      print("✅ 解码成功: addr=0x{:02x}, cmd=0x{:02x}".format(addr, cmd))
      # 保存最近有效命令(用于 repeat)
      if KEEP_LAST_ON_VALID:
            state['last_cmd'] = cmd
            state['last_addr'] = addr
            state['last_time'] = ticks_ms()
      # 执行示例动作
      handle_action(addr, cmd)
    else:
      # 错误或重复码
      if cmd == IR_RX.REPEAT:
            # REPEAT: 使用上次地址(NEC 接收端会把 addr 设为上次的 addr)
            # 这里调用 repeat 处理函数
            handle_repeat()
      else:
            # 其它错误:交给 print_error 打印可读信息
            print_error(cmd)

# 初始化接收器
rx = NEC_8(Pin(RX_PIN, Pin.IN), ir_rx_callback)

print("NEC 发射/接收测试已启动")
print("TX_PIN={}, RX_PIN={}".format(TX_PIN, RX_PIN))
print("LOOPBACK_TEST =", LOOPBACK_TEST)
print("按 Ctrl-C 退出")

try:
    # 主循环:如果启用 LOOPBACK_TEST,则定期发射测试命令,并观察接收回调
    while True:
      if LOOPBACK_TEST:
            print("\n&gt;&gt;&gt; 发射测试 NEC 命令: addr=0x{:02x}, data=0x{:02x}".format(TEST_ADDR, TEST_DATA))
            # transmit 会在底层等待 busy() 清空
            tx.transmit(TEST_ADDR, TEST_DATA)
            # 等待一小段时间再发送 repeat 测试(长按模拟)
            sleep_ms(500)
            print("&gt;&gt;&gt; 发射 repeat(模拟长按)")
            tx.repeat()# 发一个 repeat 帧
            # 多次 repeat 演示(可注释)
            sleep_ms(180)
            tx.repeat()
            sleep_ms(180)
            tx.repeat()
            # 等待下一次完整发送
            sleep_ms(SEND_INTERVAL_MS)
      else:
            # 如果不发射,仅空循环等待接收器回调触发
            sleep_ms(200)
except KeyboardInterrupt:
    print("\n终止:用户请求退出")
finally:
    # 清理接收器(解除中断等)
    try:
      rx.close()
    except Exception as e:
      print("关闭 rx 时异常:", e)
    # 如果需要可以关闭发射资源(库中没有统一的 close 接口)
    print("已退出,资源已清理(如有)。")
</code></pre>
<p>同时按照 AI 提示,注意硬件接线:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235854702-382996110.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235858017-46660779.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202509/2591203-20250907235901836-1649001924.png"></p><br><br>
来源:https://www.cnblogs.com/FreakEmbedded/p/19078922
頁: [1]
查看完整版本: 10倍效率读代码!AI神器助你秒懂任何陌生项目(保姆级教程)