news 2026/9/2 22:34:58

用51单片机实现月薪喵跳舞:LED点阵+舵机+蜂鸣器完整教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用51单片机实现月薪喵跳舞:LED点阵+舵机+蜂鸣器完整教程

最近在折腾一个小项目:想用单片机做一个会跳舞的桌面电子猫,也就是把“月薪喵”这个梗变成看得见摸得着的东西。本来以为点个灯、转个舵机就行,结果真正动起手来,发现“让猫跳舞”这件事,涉及的知识点比想象中多很多——LED点阵动画、舵机动作、蜂鸣器节奏、定时器调度,再加上任务切换和时序同步,几乎把单片机常用的外设都串起来了。

这篇文章我打算用“问题版”的方式,把我踩过的坑和最终跑通的方案整理出来。没有太玄乎的高端技术,多数知识点都是51单片机时代就有的基本功,但它们组合在一起时,容易在一堆细节上翻车。不管你是刚学单片机的新手,还是准备做趣味电子设计的老手,希望这篇教程能帮你少走几步弯路。

我会分成下面几个部分展开:先讲清楚“月薪喵跳舞”到底是什么需求,再列出硬件选型和环境准备,然后拆解LED点阵、舵机、定时器这些核心原理,最后给出一个完整的工程示例。代码都放在相应的章节里,可以照着抄下来试试。

1. 月薪喵为什么要“跳舞”——先弄清楚需求

1.1 “单片机跳舞”到底是什么意思

先解释一个容易误解的问题:单片机本身不会像人一样扭动,所谓“让月薪喵在单片机上跳起舞来”,本质上是通过单片机控制外部执行设备,让一个具体的物理对象做出类似舞蹈的动作。

通常有几种常见做法:

  • 用LED点阵屏播放帧动画,把一只猫的跳舞过程变成逐帧画面,类似小时候玩过的像素游戏。
  • 用舵机带动纸模型或3D打印的小猫,让四肢和头按照预设角度摆动。
  • 用蜂鸣器播放一小段音乐,让动画和动作跟着节奏走,更有“跳舞”的感觉。

做得好的话,这三部分可以同时运行:点阵屏上猫在蹦跶,舵机驱动的小猫摆件也在扭,蜂鸣器放着音乐,节奏还对得上。这就是这次项目的整体目标。

1.2 做这个小项目需要哪些技术点

从技术栈来看,这个项目涉及以下几个核心模块:

  • GPIO控制,用于点亮LED、驱动蜂鸣器、输出PWM信号控制舵机。
  • 定时器,用于生成稳定的时间基准,让动画帧率、音乐节拍和舵机角度切换都能按时发生。
  • LED点阵扫描,用动态扫描的方式让点阵屏显示图案,同时保证亮度均匀、不闪烁。
  • PWM舵机控制,通过调节高电平脉宽改变舵机角度。
  • 任务调度思路,让显示、动作、声音三个任务互不阻塞地交替执行。

如果你以前做过51单片机的流水灯、电子时钟、舵机小实验,那么上面这些知识点你肯定都接触过,只是没有组合到一起。

1.3 常见方案对比

实现方案效果难度适合人群
只做LED点阵动画像素风猫在屏幕里跳舞刚入门,想快速看到效果
只做舵机动作实体小猫晃动身体有舵机,想实战PWM控制
LED + 舵机 + 蜂鸣器视觉、动作、声音同步较高想完成一个综合小作品

我的建议是:第一次做,先把数字和模拟的结合点跑通,比如先用LED点阵做一个跳舞的像素猫,再加舵机动作;等这两部分都稳定后再加入音乐,最后做节奏同步。不要一开始就追求“完美舞台效果”,那是给自己挖坑。

2. 环境准备与硬件选型

2.1 单片机开发板怎么选

这个项目对主控芯片的要求其实不高,51单片机就足够应付。原因很简单:LED点阵扫描和舵机控制都不需要复杂的浮点运算,定时器中断处理小任务完全够用。

如果你手里已经有STC89C52、AT89S52或者兼容51内核的开发板,可以直接上手。如果手上是STM32,也能做,只是换个HAL库的写法,整体思路不变。

要注意一个坑:不是所有开发板都适合直接驱动点阵屏和舵机。点阵屏如果直接灌入电流太大,单片机的IO口可能扛不住;舵机启动瞬间电流也能到几百毫安甚至更高。所以选板子时优先看是否预留了外部电源接口,能不能把点阵和舵机的电源单独供电。

本文的示例以51单片机开发板为例,代码使用 Keil C51 编写。版本方面的要求如下:

- 操作系统:Windows 10 / 11 均可,Linux 也可以,但烧录软件多为 Windows 版 - 集成开发环境:Keil C51(uVision 4 或 5) - 单片机型号:STC89C52RC(示例以 12MHz 晶振为例) - 烧录工具:STC-ISP - 仿真工具:Proteus(可选,用于先跑通逻辑)

注意:如果你用的是不同频率的晶振,定时器初值要按实际频率重新计算,这个我后面会在原理部分再讲一遍。

2.2 需要用到的模块与接线

我最终用到的模块如下:

模块规格作用
主控板51单片机最小系统跑代码
LED点阵屏8x8 共阴/共阳显示跳舞动画
舵机SG90 9g控制小猫肢体动作
蜂鸣器有源蜂鸣器播放节奏提示音
电源5V 供电,至少1A以上给板子和舵机供电
按键轻触按键切换舞蹈动作

接线可以按下面这张思路来:

LED点阵: - 行引脚接 P0(低电平有效或高电平有效,取决于点阵模块) - 列引脚接 P2(通过74HC595或直接IO拉高) SG90舵机: - 信号线接 P1.0 - 电源接5V外部电源 - 地线共地 蜂鸣器: - 信号线接 P1.1 按键: - 输出接 P3.2,外部中断0触发

如果你的点阵屏没有集成驱动芯片,我强烈建议先加一片74HC595或者用共阴译码器,不要直接用P0和P2同时硬推16根线,不然扫描帧率上去了,亮度反而可能不够,还会把IO口电流顶满。

2.3 软件工具准备

软件方面需要这几样:

  • Keil C51,用来写代码、编译、生成Hex文件。
  • STC-ISP,用来把Hex烧进STC芯片。
  • Proteus,可选。如果你手头没有开发板,可以先在Proteus里搭电路,把代码逻辑验证一遍再买实物。

版本不用太纠结,能编译C51代码就行。重点是你创建工程时要选对芯片型号,并在魔法棒(Options for Target)里把晶振频率改成与实际开发板一致,否则定时器算出来的初值会偏。

3. 核心原理拆解

3.1 LED点阵屏如何显示动画

8x8点阵屏本质上是64个LED灯按矩阵排列。控制方式不能一次性点亮64个灯,因为IO口不够用,而且驱动电流也不允许。常见的做法是动态扫描:一次只点亮一行,快速切换行,利用人眼的视觉暂留,看起来就像是整屏同时在亮。

也就是说:

  • 先给第一行的8个LED赋值,
  • 把第一行选通,
  • 保持1ms到2ms,
  • 切换到第二行,
  • 依次扫完8行之后,再回到第一行。

这个过程不断循环。只要扫描频率够高,比如每秒扫200次,人眼就感觉不到闪烁。

对于“月薪喵跳舞”这种动画,实现思路是准备多帧画面。比如一帧是“猫站立”,一帧是“猫抬手”,一帧是“猫抬脚”。每帧都用一个8x8的二维数组存好,主循环或定时中断里按节奏切换当前帧索引。

关于共阴和共阳的区别:共阴点阵,给行高位点亮那一行,列给低电平让LED导通;共阳则相反。你买到的模块通常是共阴或者共阳,代码里的取反逻辑要跟着改。一个通用办法是:先把显示数据准备好,然后在写出函数里根据模块类型统一取反,这样上层动画数据不受硬件差异影响。

3.2 舵机如何控制猫的肢体动作

SG90舵机的工作原理是:通过一个20ms左右的周期脉冲,改变其中高电平的宽度,从而控制舵机转到不同角度。

一般对应关系如下:

0度 → 高电平约 0.5ms 90度 → 高电平约 1.5ms 180度 → 高电平约 2.5ms

具体数值会有微小差异,不同舵机品牌不完全一样,但大致就是这个范围。

对于51单片机,可以用定时器生成一个固定间隔的中断,比如每0.1ms进入一次中断;然后在中断里做“脉宽计数”。比如一个角度需要1.5ms高电平,那么就在1.5ms时间内让引脚保持高电平,剩下18.5ms保持低电平。这样就能输出一个稳定的PWM波。

千万不要在主循环里用delay去做舵机PWM,因为主循环还要处理LED点阵扫描和按键检测,delay会让其他任务全部卡死。正确做法是用定时中断来产生PWM,主循环只负责“设置当前目标角度”,剩下的事交给中断。

3.3 蜂鸣器、定时器与节奏同步

蜂鸣器在这里起到的作用是音乐节拍提示。严格来说,如果要用无源蜂鸣器播放整段旋律,需要输出特定频率的方波,这会占用一个定时器。对于“跳舞”这个项目,我建议先用有源蜂鸣器,只输出高电平就能响,不涉及频率控制,简单省事。

节奏同步是项目里最容易乱的部分。我们用一个舞蹈拍子,比如每0.4秒切换一个动作,那么:

  • 点阵屏的动画帧切换要按这个拍子。
  • 舵机的目标角度也要按这个拍子变化。
  • 蜂鸣器可以在每个拍子开始瞬间响一下,或者在动作切换时提示一下。

这时最好定义一个全局的“节拍计数器”。在定时中断中累加,比如每10ms计一次,计数到40时表示0.4秒过去了,就把“节拍标志”置1。主循环检测到这个标志后,就去做动画帧切换、舵机角度切换、蜂鸣器短鸣。这样三件事就同步了。

这里有一个容易踩的坑:如果在定时中断里直接切换舵机角度,会导致脉宽突然变化,电流冲击大时可能让舵机抖动甚至卡住。比较稳妥的做法是中断里只做计数和标志位,角度切换放到主循环里执行。

4. 完整实战:让月薪喵在单片机上跳起来

4.1 创建项目结构与引脚分配

先按下面结构规划工程目录:

dance_cat/ ├── main.c ├── display.c ├── display.h ├── servo.c ├── servo.h ├── timer.c ├── timer.h └── melody.c

引脚分配如下:

P0 -> 8x8点阵屏行引脚(或列引脚,根据模块资料调整) P2 -> 8x8点阵屏列引脚 P1.0 -> SG90舵机 P1.1 -> 有源蜂鸣器 P3.2 -> 按键(外部中断0,用于切换舞蹈动作)

如果你的点阵屏需要P0和P2之外的控制引脚,就按实际模块改动。下面我以常见8x8点阵模块为例,假定它是共阴点阵,P0输出高电平选通行,P2输出低电平点亮列。

4.2 编写LED点阵动画驱动

先定义两帧简单的“跳舞猫”画面。每帧8行,每行8个bit。这里用1表示亮点,0表示灭点。

// display.h #ifndef __DISPLAY_H__ #define __DISPLAY_H__ void Display_Init(void); void Display_ShowFrame(unsigned char col); #endif
// display.c #include <reg52.h> #include "display.h" #define FRAME_ROWS 8 // 共阴点阵,1 表示点亮 // 帧0:猫站立 unsigned char code catStand[8] = { 0x00, 0x3C, 0x24, 0x3C, 0x24, 0x24, 0x18, 0x00 }; // 帧1:猫抬手 unsigned char code catWave[8] = { 0x00, 0x38, 0x28, 0x3A, 0x2C, 0x08, 0x10, 0x20 }; // 当前显示行索引 unsigned char displayRowIndex = 0; void Display_Init(void) { P0 = 0x00; P2 = 0xFF; } void Display_ShowFrame(unsigned char col) { // col决定当前显示哪一帧 unsigned char dataBuffer[8]; if (col == 0) { for (unsigned char i = 0; i < FRAME_ROWS; i++) { dataBuffer[i] = catStand[i]; } } else { for (unsigned char i = 0; i < FRAME_ROWS; i++) { dataBuffer[i] = catWave[i]; } } // 动态扫描:一次显示一行 for (unsigned char row = 0; row < FRAME_ROWS; row++) { P0 = 0x00; P2 = 0xFF; P0 = (1 << row); // 选中当前行 P2 = ~dataBuffer[row]; // 共阴点阵列低电平点亮 delay_ms(1); } P0 = 0x00; P2 = 0xFF; }

这里的delay_ms函数你可以写在 main.c 里,也可以用定时器延时。先用简单延时跑通功能,后面再改成定时器驱动。

注意:上面的dataBuffer是局部数组,每次扫描都会重新复制帧数据,这是为了让扫描函数统一接口。实际项目如果内存吃紧,可以直接在扫描函数里用指针访问 code 数组,避免复制。51单片机的RAM很小,经验不足时最容易栽在这里。

4.3 编写舵机动作驱动

下面用定时器0产生0.1ms中断,用软件方式产生PWM。

// servo.h #ifndef __SERVO_H__ #define __SERVO_H__ void Servo_Init(void); void Servo_SetAngle(unsigned char angle); #endif
// servo.c #include <reg52.h> #include "servo.h" sbit ServoPin = P1^0; #define SERVO_PERIOD 200 // 20ms = 200 * 0.1ms unsigned int pwmCount = 0; unsigned int highTime = 15; // 1.5ms高电平,对应90度 void Servo_Init(void) { ServoPin = 0; // 定时器0初始化,方式1,16位定时 TMOD &= 0xF0; TMOD |= 0x01; TH0 = 0xFF; // 12MHz晶振,0.1ms初值 TL0 = 0x9C; ET0 = 1; EA = 1; TR0 = 1; } void Servo_SetAngle(unsigned char angle) { // angle取值范围:0~180,映射到0.5ms~2.5ms // 即 5~25 个 0.1ms 计数周期 highTime = 5 + (unsigned int)((unsigned long)angle * 20 / 180); } void Timer0_ISR(void) interrupt 1 { TH0 = 0xFF; TL0 = 0x9C; pwmCount++; if (pwmCount < highTime) { ServoPin = 1; } else { ServoPin = 0; } if (pwmCount >= SERVO_PERIOD) { pwmCount = 0; } }

这里的关键点是:TMOD的低四位初始化0x01,表示定时器0工作在方式1,也就是16位定时器。为了“为什么这么写”,多提一句:如果你同时用了定时器1去做其他事情,不要直接TMOD = 0x01,应该像示例里那样先高位清零再低位赋值,避免把定时器1的工作方式改坏。

12MHz晶振下一个机器周期是1us,定时器0每0.1ms需要计数100次。初值计算为65536 - 100 = 65436,也就是0xFF9C。如果你的晶振不是12MHz,需要按公式重新算:

初值 = 65536 - (定时时间秒 * 晶振频率Hz / 12)

4.4 编写主循环与节奏控制

把点阵、舵机和蜂鸣器都关联起来。定义一个全局节拍计数器,每0.4秒切换一次动作。

// main.c #include <reg52.h> #include "display.h" #include "servo.h" sbit Buzzer = P1^1; sbit Key = P3^2; #define DANCE_STEP_TIME 40 // 40 * 10ms = 400ms unsigned char stepCount = 0; unsigned char danceStep = 0; unsigned char animationCol = 0; // 当前帧 unsigned char keyFlag = 0; void delay_ms(unsigned int ms) { unsigned int i, j; for (i = 0; i < ms; i++) { for (j = 0; j < 123; j++) { ; // 空延时,具体数值与晶振有关 } } } void Timer1_Init(void) { TMOD &= 0x0F; TMOD |= 0x10; // 定时器1,方式1 TH1 = 0xD8; // 10ms定时初值(12MHz) TL1 = 0xF0; ET1 = 1; EA = 1; TR1 = 1; } void Timer1_ISR(void) interrupt 3 { TH1 = 0xD8; TL1 = 0xF0; stepCount++; if (stepCount >= DANCE_STEP_TIME) { stepCount = 0; // 节拍到,标记主循环处理 keyFlag = 1; } } void External0_ISR(void) interrupt 0 { // 按一下按键,切换舞蹈动作 danceStep++; if (danceStep > 1) { danceStep = 0; } } void ProcessDanceStep(void) { // 每个节拍执行一次 switch (danceStep) { case 0: animationCol = 0; // 显示站立帧 Servo_SetAngle(90); // 舵机回中 Buzzer = 1; // 响一下 delay_ms(50); Buzzer = 0; break; case 1: animationCol = 1; // 显示抬手帧 Servo_SetAngle(0); // 舵机左摆 Buzzer = 1; delay_ms(50); Buzzer = 0; break; default: break; } } void main(void) { Display_Init(); Servo_Init(); Timer1_Init(); P3 = P3 | 0x04; // P3.2 输入模式,上拉 IT0 = 1; // 外部中断0下降沿触发 EX0 = 1; // 开启外部中断0 EA = 1; while (1) { if (keyFlag) { keyFlag = 0; ProcessDanceStep(); } // 点阵扫描不停,这里每帧都刷新显示 Display_ShowFrame(animationCol); } }

这里要注意:ProcessDanceStep()里调用delay_ms(50)是为了让蜂鸣器响50ms,但这个延时会在主循环里造成短暂阻塞。在实际项目里,我推荐改成“蜂鸣器定时计数”的方式,比如先置1,再启动一个滴滴标志,等定时器计数到50ms后自动置0。这样点阵扫描完全不卡。不过在初版演示代码里,为了好理解,先用延时也是可以的。

另外关于keyFlag的名称,严格来说它代表“节拍标志”,不是按键标志。我这里为了少写一个变量直接复用了。写代码时你可以改成beatFlag,更清晰。

4.5 烧录与验证

在Keil里编译生成Hex文件后,用STC-ISP烧录到开发板。烧录步骤大致是:

  1. 选择单片机型号为STC89C52RC。
  2. 打开生成的Hex文件。
  3. 连接USB转串口线,选择对应串口号。
  4. 点击下载,然后给开发板断电重新上电。
  5. 下载成功后,观察点阵屏是否交替显示两帧动画,舵机是否在0度和90度之间摆动。

输出结果预期:

  • 点阵屏每隔0.4秒切换一次画面,第一帧是“猫站立”,第二帧是“猫抬手”。
  • SG90舵机先回中到90度,再转到0度,不断循环。
  • 每个节拍开始时蜂鸣器短响一声。
  • 按下P3.2按键后,会切换另一套舞蹈节拍,也就是把danceStep切到另一组状态。

如果一切正常,月薪喵就真的在单片机上“跳”起来了。

5. 常见问题与排查思路

5.1 点阵屏显示闪烁

这个比较常见。可能原因有两个:一是扫描频率太低,二是在扫描过程中被延时函数卡住。

排查思路:

问题现象常见原因解决思路
点阵屏整体闪烁扫描循环内延时太长把每次扫描延时降到1ms左右
只有一行亮行选通或列数据没对检查P0、P2的极性,是否需取反
画面重影行切换时没有先消隐每行显示前先清空所有IO,再写下一行数据
亮度不均匀某一帧重复扫描次数少在主循环里保证不同动画帧的刷新次数接近

5.2 舵机一直抖动或不动

舵机抖动通常不是程序问题,而是电源问题。SG90转动瞬间电流比较大,如果用开发板的USB口或小功率电源,电压会被拉低,导致舵机内部控制电路不停复位。

排查顺序:

  1. 用万用表测舵机电源电压,转动瞬间是否掉到4.5V以下。
  2. 换一个独立5V电源给舵机供电,板子与舵机共地。
  3. 检查PWM周期是否接近20ms,如果周期偏差较大,舵机会嗡嗡响。
  4. 检查P1.0引脚是否有高电平输出,以及信号线是否接对。

5.3 定时器冲突

如果同时使用了定时器0和定时器1,中断服务函数分别是interrupt 1interrupt 3。写错中断号的话,代码不会编译报错,但运行时会进入错误的中断入口,导致程序跑飞。

中断源中断号
外部中断00
定时器01
外部中断12
定时器13
串口4

另外注意:如果定时器1已经用于串口波特率,建议不要再用它做节拍定时。可以改用定时器2,或者把节拍计数放在定时器0里一起处理。

5.4 按键切换不灵敏

原因是按键没有消抖,或者外部中断被其他程序里的开关噪声触发。最简单的处理是加入一个30ms到50ms的软件消抖,在中断服务函数里加一个延时。但更好的做法是:中断里只把intFlag置1,在主循环里延时消抖后再读取按键电平。

void External0_ISR(void) interrupt 0 { // 简单的防抖:连续两次间隔确认 TMOD |= 0x20; // 临时使用定时器1方式2,但这里只是示意 // 实际项目建议在主循环中处理消抖 keyIntFlag = 1; }

这个代码片段只是思路,不要直接照抄到自己的工程里。真正合适的做法是去掉中断,改成在主循环扫描按钮,用15ms延时消抖。这样代码更简单,也不容易干扰其他中断。

5.5 编译报错找不到 reg52.h

这通常是因为Keil工程没有选择正确的芯片设备。在Keil uVision中点击“Options for Target -> Device”,选择Atmel下的AT89C52,或者STC目录下的STC89C52RC。如果不确定,直接选AT89C52就能编译通过大部分C51项目。

6. 最佳实践与工程建议

6.1 模块化设计,不要都堆在main.c里

把点阵、舵机、定时器、旋律分别写成独立的C文件和H文件,主函数只负责逻辑编排。这样后续想换一种点阵屏、换一个舵机型号,只要改对应的驱动文件,不会动主逻辑。

这个项目本身不大,但等你以后做智能小车或电子时钟时,模块化会显著降低调试难度。特别是51单片机没有操作系统,所有任务都要自己调度,文件职责清晰能省下很多查错时间。

6.2 用定时器代替完整延时函数

做主循环里的大延时,比如“甩手1秒后回归”这种设计,建议用状态机加定时器计数实现。不要在某个状态里用delay_ms(1000)阻塞整个循环,否则点阵就没法刷新了。

一个常见写法是:

// 定义一个定时状态变量 unsigned char actionTimer = 0; // 定时中断里累加 void Timer1_ISR(void) interrupt 3 { // ... if (actionTimer > 0) { actionTimer--; } } // 主循环里执行动作切换 void ProcessAction(void) { if (actionTimer == 0) { switch (currentAction) { case ACTION_WAVE: Servo_SetAngle(0); actionTimer = 40; // 0.4秒后执行下一个动作 currentAction = ACTION_STAND; break; case ACTION_STAND: Servo_SetAngle(90); actionTimer = 40; currentAction = ACTION_WAVE; break; } } }

这套思路其实就是最简单的“时间片状态机”,比无限循环加delay要可靠得多。

6.3 注意电源分配

单片机的IO口能输出的电流有限,单个引脚一般不要超过20mA。LED点阵如果把8个LED同时点亮,电流可能超过100mA,所以最好通过三极管或74HC245等驱动芯片来扩展。

舵机电源也不要和单片机共用同一个稳压模块。尤其在使用9V电池或USB供电时,舵机一启动,CPU就可能复位。正确接法如下:

外部5V电源 → 舵机电源 外部5V电源 ← 开发板电源输入 GND 公用地线

这样两者有共同的参考地,但供电路径分开,能避免大部分复位问题。

6.4 代码里加注释,但不要注释废话

很多初学者喜欢每行都写注释,注释内容却只是重复代码本身,比如:

P0 = 0x00; // 给P0赋0

这种注释没有价值。更好的注释是说明“为什么”:

P0 = 0x00; // 消隐,防止上一行余晖造成重影 P2 = 0xFF; // 将所有列置高,关断所有LED

对“月薪喵跳舞”这种项目来说,你很可能做完后隔几周再回来改动作,只有注释写了“为什么这样设定帧顺序”和“这个节拍对应哪段动作”,才能快速找回状态。

6.5 先仿真后实物

如果担心烧坏硬件,建议先画一份Proteus仿真图。8x8点阵屏、SG90舵机、蜂鸣器在Proteus里都有库可以仿真,代码逻辑可以全部验证。但要注意,仿真永远不等于实物。Proteus里不会出现电源纹波压降和舵机电流冲击问题,所以仿真通过了,上真机还是可能遇到闪烁或复位,这一点要有心理准备。

7. 总结与下一步方向

这篇文章从“月薪喵到底怎么在单片机上跳起来舞”的问题出发,拆出了LED点阵动画、舵机PWM控制、蜂鸣器节奏和定时器调度这四块内容。最终工程代码里,点阵屏负责视觉动画,舵机负责物理动作,蜂鸣器负责节拍提示,三个模块通过定时器同步在了一起。

如果要继续深入,可以尝试下面几个方向:

  • 把动画帧从2帧扩展到8帧,做一个更流畅的跳舞动作序列。
  • 用无源蜂鸣器配合定时器输出不同频率方波,让音乐变成真正的旋律。
  • 把LED点阵换成LCD1602或OLED,用字符或图形方式显示小猫状态。
  • 在点阵屏上显示实时温度或“月薪喵的今日心情”。
  • 把主控升级到STM32,用HAL库的定时器PWM输出和DMA实现更高刷新率的动画。

单片机学习最忌只看不练。我建议你拿到这篇文章后,不要只读原理,打开Keil建一个工程,先点亮点阵的一行,再让行扫描跑起来,然后接入舵机,最后再加节拍。一步一步来,一个月薪喵跳舞的小桌面摆件就能顺利做出来。

如果这篇文章对你有帮助,可以收藏备用。欢迎在评论区分享你调试时遇到的奇怪问题,大家一起交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 22:34:53

PLC梯形图编译器架构设计与实现:从图形到字节码的完整链路

简介&#xff1a;梯形图语言与继电器控制电路直观相似&#xff0c;广泛用于工业控制。这份PLC梯形图编译器源代码面向工业自动化开发者与PLC编程学习者&#xff0c;旨在帮助理解梯形图语言的编译原理&#xff0c;并为开发自定义编译工具或集成环境提供参考。压缩包共58个文件&a…

作者头像 李华
网站建设 2026/9/2 22:33:05

用Python分析乒乓球七局逆转:从逐分数据到可视化复盘

最近不少球友在讨论横滨冠军赛上松岛辉空和张禹珍那场七局大战&#xff0c;标题里“毁天灭地”这四个字虽然夸张&#xff0c;但确实把比赛最后时刻的戏剧性表达出来了。作为一名经常和数据打交道的开发者&#xff0c;我在看这类比赛时总忍不住想&#xff1a;七局逆转到底是怎么…

作者头像 李华
网站建设 2026/9/2 22:30:23

30 分钟搞定 FreeCAD 装配:从配合约束到运动仿真的完整指南

30 分钟搞定 FreeCAD 装配&#xff1a;从配合约束到运动仿真的完整指南 【免费下载链接】FreeCAD Official source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler. 项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD 想象你手里…

作者头像 李华
网站建设 2026/9/2 22:21:44

运维进阶路线:从Linux基础到Kubernetes云原生专家

运维这个岗位&#xff0c;很多人干着干着就变成了“高级打杂”&#xff1a;装系统、重启服务、改密码、回领导消息。真要说技术积累&#xff0c;三年下来可能除了熟记几条 Linux 命令&#xff0c;产出少得可怜。这次我们不聊虚的&#xff0c;就讲清楚一件事&#xff1a;运维如何…

作者头像 李华
网站建设 2026/9/2 22:21:14

HarmonyOS APP地址管理开发:“美寇商城”的收货地址跨端存储方案

在万物互联的鸿蒙生态中&#xff0c;用户可能在手机浏览“美寇商城”&#xff0c;在平板上填写收货地址&#xff0c;最终在智慧屏上确认订单。一套能将收货地址无缝流转于所有设备间的跨端存储方案&#xff0c;正是提升这类全场景购物体验的核心。本文将深入解析美寇商城如何利…

作者头像 李华
网站建设 2026/9/2 22:20:23

DeepSeek-V4-Pro 接入 Codex CLI:配置、排错与识图 Skill 指南

DeepSeek-V4-Pro 接入 Codex 的难点不在模型本身&#xff0c;而在配置模型名、指定 API 地址、处理客户端校验报错这三个环节。这篇教程会从零开始&#xff0c;先安装最新版 Codex CLI&#xff0c;再把 DeepSeek-V4-Pro 配成 Codex 的模型提供方&#xff0c;最后通过一个识图 S…

作者头像 李华