
简介面向九齐科技NY8系列单片机开发者的例程合集适合电子工程、自动化控制与嵌入式系统设计人员参考无论是课程设计、毕业设计还是产品原型验证都能从中找到可用代码。内容覆盖C语言与汇编语言两套编程思路从输入输出、定时器、中断处理到串行通信、模数转换等常用外设均有示例既有适合复杂逻辑的C代码也有可直接控制硬件的汇编例程可帮助初学者快速上手也能为工程师提供可复用的底层代码。资源包共2901个文件包含C源码、汇编源码、头文件以及工程文件与构建脚本压缩包整体4.35MB结构清晰便于在开发环境中直接打开和编译。目前已有13607人学习下载是NY8系列开发中较热门的参考资源。通过逐个例程读者可以理解寄存器配置、时序控制、中断响应等关键操作并掌握不同型号间的差异与代码移植方法为实际项目开发打下扎实基础。1. 先说清楚NY8 这颗芯片到底什么来路很多朋友第一次听到九齐单片机是在淘宝搜料或者供应商推荐的时候。九齐Nyquest是台湾一家老牌 MCU 设计公司主打的就是高性价比 8 位 OTP 单片机。NY8 系列是它最常被用到的一条产品线代表型号有 NY8A051F、NY8A053E、NY8A054E、NY8A062D 这些。为什么这颗芯片在小家电、玩具、LED 灯控、PIR 人体感应模块里出镜率那么高核心原因就一个字省。NY8 系列内部是 OTP 工艺也就是一次可编程价格压得很低适合大批量出货、固件基本不变的产品。比如你家里那个便宜的红外感应小夜灯、几十块钱的电子蜡烛、玩具枪的声光效果板里面很可能就是 NY8A051F 这类芯片。这颗芯片的资源其实很朴素程序空间一般只有 1K~2K wordSRAM 也就几十个字节IO 口数量根据封装不同有 8 到 18 个不等。听起来很寒酸但做逻辑控制、PWM 调光、按键扫描、简单传感器读取完全够用。它内置了定时器、PWM、ADC、WDT还有低功耗休眠模式整体外设对于一个成本敏感的消费类产品来说非常够用。说到例程就不得不提一个现实问题九齐官方资料的风格属于能用就行数据手册写得比较简单官方例程也不是特别丰富。很多新手拿到一颗 NY8 芯片对着数据手册里的寄存器列表一头雾水这时候一份能直接编译烧录的例程就是最好的老师。所以这篇博文我不打算只给你贴代码而是把例程背后的原理、开发环境、烧录流程、踩坑经历一起讲明白让你不只是能跑例程而是会改例程。适合看这篇文章的人分两类一类是从 STM32、PIC 等平台转过来的工程师想快速上手九齐这颗低成本芯片另一类是刚接触单片机、手里只有一块 NY8 开发板的新手想知道这些例程到底是什么意思、怎么用。无论哪类我建议你手里先准备好数据手册和例程工程包边看边对照效果最好。2. 开发环境搭建与例程工程结构2.1 工具链Oscillate IDE 与烧录器选型九齐的开发环境叫 Oscillate IDE也常被叫做 NY9 系列 IDE这个 IDE 集成了编辑器、编译器、软件仿真器和烧录工具。第一次打开这个 IDE 时你会觉得界面有点古早味但功能层面是完整的C 和汇编都支持内置的软件模拟器Simulator在 OTP 芯片场景下非常关键。我强烈建议你养成先仿真、后烧录的习惯。因为 NY8 是 OTP 芯片烧进去就擦不掉如果代码有 bug整颗芯片就废了。Oscillate IDE 的 Simulator 可以模拟大部分外设行为包括 IO 翻转、定时器中断、PWM 输出虽然不能 100% 模拟真实电气特性但逻辑层面的 bug 基本都能在仿真阶段暴露出来。烧录器方面九齐官方有对应的烧录器淘宝上也有很多第三方的九齐烧录器兼容性尚可但偶尔有坑。我的建议是如果是小批量打样用开发板自带的烧录功能就行如果准备量产建议投资一个官方烧录器顺便可以做烧录产能和良率统计。烧录器与芯片之间一般就是 VDD、GND、CLK、DIO 四条线部分型号还支持在线烧录具体引脚定义一定要查对应型号的数据手册不同封装的烧录脚位不一样接错了容易烧片子。2.2 例程包里通常有哪些文件从代理商或开发板卖家那里拿到的九齐例程包通常长这样每个例程一个文件夹里面有.osc工程文件、.c或.asm源文件、.h头文件还有用来说明例程用途的 README 或 PDF 文档。.osc文件是 Oscillate IDE 的工程文件双击打开就能载入整个工程。比较常见的例程清单包括GPIO 闪烁灯最基础用来验证芯片和烧录链路按键扫描查询方式和中断方式定时器中断PWM 调光ADC 采样电位器或光敏电阻休眠唤醒这些例程就是九齐官方或第三方工程师根据数据手册外设模块写的最小可用工程。我的经验是拿到例程包后先不要急着改功能而是把所有例程都打开编译一遍。这一步能帮你快速确认 IDE 环境有没有装好、编译器版本对不对、有没有缺头文件路径。如果连官方例程都编译不过那问题大概率出在环境配置上而不是你自己的代码上。3. 例程核心从点灯到定时器中断3.1 GPIO 例程别看简单方向寄存器必须先搞清楚点灯是单片机的Hello World。NY8 的 GPIO 例程看似简单但有几个细节新手很容易翻车。九齐的 IO 口涉及三类寄存器PORTx是数据寄存器写 1/0 控制输出电平TRISx是方向寄存器1 表示输入0 表示输出IOCx是 IO 控制寄存器用来配置上拉、开漏等选项。很多新手只设置PORTx忘了配置TRISx结果引脚怎么都不出电平其实就是方向没设对。我贴一段简化版点灯代码以假设的 PORTA 引脚为例实际引脚号以你手里芯片型号为准#include NY8A05x.h void main(void) { // 配置 PA0 为输出 TRISA 0xFE; // bit0 0输出其余保持输入 PORTA 0x01; // PA0 输出高电平 while (1) { PORTA ^ 0x01; // 翻转 PA0 delay_ms(500); // 软件延时 } }这里TRISA 0xFE的含义是TRIS 寄存器里哪一位是 0对应引脚就是输出。这个方向和很多工程师熟悉的输出写 0有些相反所以刚接触九齐的人特别容易搞混。再看PORTA ^ 0x01这是异或翻转每次循环 PA0 电平取反LED 就一亮一灭。在实际项目中GPIO 例程最大的坑还不是方向寄存器而是 IO 复用。NY8 很多引脚是复用的同一个引脚既可能是普通 GPIO也可能是 PWM 输出或 ADC 输入必须在IOCx或对应外设控制寄存器里正确配置否则引脚会保持高阻或默认状态。遇到引脚不听指挥的情况先去查数据手册的 Pin Function 表看这个引脚默认复用功能是什么再决定往哪个寄存器写值。3.2 定时器中断例程精度和时间基准的关键有了点灯基础第二个必学例程是定时器中断。九齐 NY8 系列内部有多个定时器资源常见的比如 T16 是 8 位定时器可以自由运行或者分频。定时器例程一般干两件事设定分频系数和初值然后在中断服务函数里做周期性的处理。中断例程的代码结构大概如下volatile unsigned int tick 0; void isr(void) __interrupt(0) { if (INTF T16_INT_FLAG) // 判断定时器中断标志 { INTF T16_INT_FLAG; // 清除中断标志 tick; PORTA ^ 0x01; // 每次中断翻转LED } } void main(void) { TRISA 0xFE; PORTA 0x01; // 配置 T16 定时器分频、使能中断具体寄存器以头文件为准 T16_CTRL 0x02; // 假设开启分频 INTF 0; // 清空中断标志 INTE | T16_INT_EN; // 使能定时器中断 __engint(); // 开启全局中断 while (1) { // 主循环可以做别的事比如按键扫描 } }这段代码里有几个关键点我必须展开讲第一中断标志位需要软件手动清除。如果不清标志中断会反复进入看起来像死循环一样。九齐的中断标志写在INTF寄存器里处理完对应事件后一定要写回清除。第二中断服务函数的写法在不同编译器版本里略有差异旧版 C 编译器可能用void interrupt isr(void)新版可能用__interrupt(0)这种扩展写法。遇到编译报错时先看例程自带的写法以例程为准。第三定时器初值的计算要自己动笔算。8 位定时器从初值开始计数溢出到 256 产生中断。假设芯片内部时钟是 4MHz定时器分频比是 1:64那么定时器时钟频率是 4MHz/64 62.5kHz周期约 16 微秒。想让 LED 每 100 毫秒翻转一次就需要计数时间约 100ms / 16us ≈ 6250 次但 8 位定时器最多只能从 0 数到 255所以不能单靠 T16 软件定时通常还会在中断里再用一个变量做分频计数。这就是tick变量的作用用软件计数器扩展定时范围。3.3 PWM 例程低成本调光和电机调速的基础PWM 是九齐 NY8 例程里非常实用的一个模块毕竟很多客户拿它做 LED 灯控比如小夜灯无级调光、RGB 灯渐变。NY8 的 PWM 模块通常支持多通道输出占空比由 PWM 数据寄存器控制频率由系统时钟和分频器决定。PWM 例程的关键配置项包括时钟源选择、分频比例、周期值、占空比初始值、输出引脚选择。以呼吸灯为例思路就是让占空比从一个方向慢慢递增到 100%再递减回 0%循环往复。void set_pwm_duty(unsigned char duty) { PWM_DUTY duty; // 假设 PWM_DUTY 寄存器控制占空比 } void main(void) { PWM_CTRL 0x01; // 使能 PWM 模块选择时钟源 TRISB 0xFE; // PWM 输出引脚设为输出 unsigned char duty 0; while (1) { for (duty 0; duty 255; duty) { set_pwm_duty(duty); delay_ms(3); } for (duty 255; duty 0; duty--) { set_pwm_duty(duty); delay_ms(3); } } }PWM 例程最大的坑是输出引脚映射。NY8 的 PWM 功能不是所有引脚都有的只有特定的引脚能输出 PWM 信号。如果你随便接一个 GPIO 然后怎么配置都不出波形八成是引脚号选错了。这种问题光靠看程序是看不出来的必须对照数据手册的引脚功能表一个个查。另外PWM 输出在芯片刚上电的一瞬间可能是高电平也可能是低电平取决于默认寄存器值。如果产品对这一点很敏感比如驱动 LED 时不想上电闪一下可以在初始化时先把占空比设为 0再打开输出使能这算是一个细节经验。4. 例程落地实操从编译烧录到扩展调试4.1 完整跑通一个例程的流程光看代码不动手永远是纸上谈兵。这里我按自己的实际操作顺序把从拿到例程到芯片点亮的完整流程列一遍解压例程包用 Oscillate IDE 打开.osc工程文件。在工程设置里确认芯片型号比如 NY8A051F。如果型号不对编译可能报错或者烧录时芯片不识别。点编译按钮确认没有报错。如果提示缺少头文件在工程 include 路径里添加九齐头文件目录。打开 Simulator点运行观察寄存器变化和变量值。这一步能提前发现逻辑错误。连接烧录器和芯片。接线顺序建议先接 GND再接 VDD最后接 CLK 和 DIO避免热插拔造成电平冲击。在 IDE 里选择烧录器型号和芯片型号加载编译生成的.hex或.bin文件点烧录。烧录完成后给芯片上电观察 LED 或逻辑分析仪波形。这里有一个非常容易踩的坑烧录器给芯片供电时芯片必须处于空闲状态不能同时接外部电源否则可能出现电平冲突甚至烧毁 IO 口。多组电源同时存在时要么通过跳线帽切换要么严格保证上电顺序。4.2 例程扩展把点灯改成按钮控制的呼吸灯我习惯用改例程来验证自己是否真的理解了。比如官方给了一个点灯例程和一个 PWM 例程你可以试着把它们合并成一个新功能按下按键LED 开始呼吸灯效果再按一下LED 熄灭。这个过程中涉及的知识点包括 GPIO 输入、按键消抖、PWM 占空比更新。unsigned char key_pressed(void) { if ((PORTB 0x01) 0) // 假设按键接在 PB0按下为低 { delay_ms(10); // 消抖 if ((PORTB 0x01) 0) { return 1; } } return 0; }按键消抖为什么用 10ms 延时而不是 1ms因为机械按键的抖动时间通常在 5ms~15ms10ms 是一个比较折中的值。消抖本质上就是延时后再确认一次电平逻辑很简单但能极大地减少误触发。扩展例程时要特别注意全局变量和中断共享问题。我用tick变量在中断里计数PWM 亮度变化在主循环里读这个变量如果主循环读取的同时中断更新了它理论上可能读到撕裂值。对这种低成本 8 位单片机、非高频场景问题不大但养成中断里改的变量用 volatile 修饰的习惯永远是对的。4.3 用逻辑分析仪验证例程是否真正常很多时候程序写完了、烧录也成功但产品表现不如预期这时候不要盲目改代码先拿逻辑分析仪或示波器测一下引脚波形。我就遇到过一次 PWM 例程完全按官方代码跑但 LED 亮度不均匀的情况最后是拿示波器看波形才发现占空比更新频率和 PWM 周期不同步导致一个周期内亮度跳变。逻辑分析仪在这种低成本芯片调试里非常实用几百块的设备就能满足需求。接上信号线抓取引脚电平变化你就能直观看到GPIO 翻转周期对不对、PWM 频率是否稳定、按键按下时波形有没有抖动。有了波形数据很多玄学问题其实都能归因到某个配置寄存器上。5. 常见问题与排查技巧实录5.1 烧录失败或烧录后芯片不工作这是新手遇到最多的一类问题。先检查几个基本点芯片型号是否选对烧录器驱动是否正常CLK 和 DIO 线有没有接反芯片 VDD 电压是否在规格范围内。如果烧录时提示芯片 ID 读取失败大概率是连线问题或者芯片本身已经损坏。还有一个非常容易忽视的原因代码里把烧录引脚配置成了普通 IO导致烧录时序被破坏。有些器件支持通过配置字Configuration Word禁用烧录引脚功能一旦配置错了芯片就锁死再也无法烧录。所以在例程里看到烧录引脚相关配置时不要随意改动先确认不影响烧录再去做其他操作。5.2 例程改了之后运行结果异常很多朋友会把官方例程拿过来改几个 IO 口号就能跑但改了之后发现行为不对。这时候优先排查顺序改动的引脚是否支持所要复用的功能配置寄存器时是否误操作了其他位全局中断是否被意外关闭。我印象最深的一次是把官方 PIR 感应灯例程的延时从 30 秒改成 3 秒结果上电后 LED 闪一下就再也不亮了。折腾半天发现例程里的延时函数用的是定时器中断计数值我只改了一个变量但中断服务函数里另一个计数器还在跑导致主循环逻辑陷入了一个永远不会执行到的分支。这种问题靠仿真器能很快定位所以再次强调改例程后先仿真再烧录。5.3 OTP 芯片的后悔药问题NY8 一次性编程的特性决定了它没有擦除重来的机会。如果你用的是 OTP 版本烧录之前必须确认代码万无一失。我的做法是在工程里加一个自检模式芯片上电后先跑一遍自检流程量内部电压、检查 IO 翻转、输出特定波形确认所有硬件功能正常后再进入正式应用逻辑。这样即使已经烧录至少还能通过自检信号判断芯片是否活着。如果项目还在开发阶段务必选择带仿真功能的版本或者使用开发板来调试等你把逻辑都调通了再换用 OTP 版本做小批量生产。5.4 低功耗休眠唤不醒NY8 的低功耗模式是它的卖点之一很多电池供电产品都指望它。但休眠唤醒的例程也有经典坑很多睡眠指令执行后要等到特定唤醒源比如 IO 电平变化、定时器溢出才能醒来如果唤醒源没配置正确芯片会一直睡下去看起来就像死机。排查这个问题的思路是先确认唤醒源对应的寄存器有没有开启再确认唤醒时电平变化方向是否和设置一致最后确认唤醒后的中断服务函数里有没有把标志位清干净。有一次我在休眠前把按键引脚配成了带上拉输入但唤醒条件设为检测到下降沿结果按键按下确实产生下降沿中断标志却一直没有被正确响应问题就出在唤醒配置寄存器的边缘触发位写反了。6. 例程之外一次项目实战的体会最后说点例程之外的东西。很多初学者把例程当答案以为跑通了官方例程就等于掌握了这颗芯片。但例程更像一个个零件你得自己把它们拼成一台机器。我做一个感应小夜灯项目时把 GPIO、定时器、PWM、休眠唤醒这几个例程全部拼在一起中间还额外加了几层业务逻辑比如白天不亮、电池电压过低时快闪提示这时候才发现单个例程都懂组合起来才是真正的考验。我的建议是在理解每一个例程的原理之后给自己设定一个小目标比如用两个按键控制 PWM 亮度并且按键按下时能唤醒休眠状态然后试着自己把例程改出来。这个过程会逼你去查数据手册、去理解寄存器之间的关系比单纯跑通十个例程都有效。还有一个小技巧在所有例程的主循环开头加一个空循环计数变量配合调试器或 LED 翻转能快速确认程序有没有跑飞。很多芯片死机其实是程序跑进了异常分支加几个陷阱点能帮你快速定位问题的位置。这个习惯在那次小夜灯项目里救了我很多次。九齐单片机本身不复杂复杂的是耐下心去理解它的外设和 OTP 特性。祝你能用这份例程把第一个产品跑起来等真正量产之后你会发现这颗小芯片比想象中靠谱得多。本文还有配套的精品资源点击获取