简介:本资源是一套面向嵌入式初学者与单片机课程实践者的51单片机PS2键盘接口开发例程,聚焦硬件通信协议解析、扫描码映射与抗抖动处理等核心难点,助力读者掌握串行外设驱动开发全流程。压缩包共21个文件,含3个关键头文件(.h)、3个C源码(.c)、3个目标文件(.obj)及.hex可执行镜像、.uv2工程配置、.lst编译列表等,完整覆盖Keil C51开发环境下的编码、编译、调试与烧录环节,总大小仅40KB,轻量易用。已有59人学习下载,适合高校实验课、电子设计入门及小型人机交互项目拓展。读者可直接导入Keil工程运行,通过LCD1602实时显示按键字符,结合KeyBoard.c中扫描码表与中断轮询逻辑,深入理解PS2时钟同步机制、位采集时序控制及ASCII映射实现,是少有的兼顾原理讲解与可运行代码的综合性教学资源。 拿到这块板子的时候,我第一反应是:51单片机例程源码里居然还藏着PS2键盘实验。说实话,做过几个单片机项目之后,你会发现PS2键盘这套协议虽然老,但在课程设计、毕设、甚至工业设备改造里一直没消失。它的价值在于,你把PS2协议吃透,后面接矩阵键盘、接触摸屏、接各种串行外设,思路都是通的。这篇我就把这套例程源码的完整拆解、硬件接线、代码逻辑、调试踩坑全部写出来,给正在做51单片机实验或者打算拿PS2键盘做交互的同学一份能直接抄的作业。
先说清楚这套例程能干什么:51单片机通过PS2接口读取标准键盘的按键扫描码,在数码管或LCD上显示键值,按下和松开都能识别,支持组合键扩展。适合的人群很明确——学过C语言基础、正在入门51单片机的中级选手,尤其是课程设计选中了“键盘输入+显示输出”这个经典组合的同学。硬件成本极低,一块51开发板加一个旧键盘就能跑起来,但软件里的时序处理、中断嵌套、数据校验这些点,恰恰是很多教程没讲透的地方。
1. 整体设计与思路拆解:为什么PS2协议值得手动写一遍
1.1 PS2协议的核心价值:两根线闯天下
最开始接触PS2接口的时候,我总想着是不是要什么高大上的协议芯片。实际上PS2键盘通信只有两根线——时钟线CLK和数据线DATA,外加电源和地。这个“串行协议”的精髓在于:所有数据都是按位传输,时钟线负责节奏,数据线负责内容。主机端的51单片机只需要在时钟的边沿去采样数据线的电平,就能拿到键盘发来的完整字节。
这套机制对51单片机来说特别友好。51的IO口速度虽然不快,但PS2的时钟频率通常在10kHz到16.7kHz之间,换算下来每bit大约60到100微秒,单片机完全能靠查询或者中断跟上这个节奏。对比I2C或者SPI,PS2不需要额外的地址概念,键盘是唯一的从设备,主从关系简单清晰。所以很多老工程师到现在还是喜欢用PS2键盘做“人机交互输入”,就是因为它稳定且协议透明,出了问题自己就能定位。
1.2 从例程源码看作者的协议设计思路
拿到这套例程源码,我一般先不看程序主体,而是看它的头文件定义和引脚配置。这样能最快推断出作者的硬件接法和设计意图。例程里通常会有这么几个关键点:一是CLK接在哪个引脚,这直接决定了用中断还是查询;二是DATA接在哪个引脚,决定了读取的IO操作方式;三是有没有定义键盘状态标志位,比如按下标志、松开标志、扩展码标志。这三个点想清楚了,整个程序的骨架也就出来了。
这套例程的设计思路很典型:用外部中断接收CLK下降沿,在中断服务函数里读取DATA电平,拼装成完整的字节,再用一个状态机处理扫描码。这种“中断接收+主循环解析”的结构在高实时性场景里很常见,因为它既能保证不丢数据,又不会让主循环卡在读键盘上。相比纯查询方式,中断方式让单片机在按键间隙可以腾出精力去做别的事情,比如刷新数码管、扫描传感器、跑定时器任务。
1.3 为什么不用矩阵键盘而选PS2
有同学会问,51单片机实验不是经常用4x4矩阵键盘吗?为什么还要拿PS2键盘来折腾。我的理解是:矩阵键盘适合按键数量少、布局固定的场景,但一旦你需要在项目里输入字母、数字混合的字符串,比如密码锁、温度报警阈值设置、简易计算器,4x4矩阵键盘的键值映射能把人逼疯。PS2键盘一次能上报上百个按键,通码、断码自带识别,按下和松开天然区分,这在做交互类项目时省掉大量编码工作。
而且PS2协议学一遍的价值在于“通用性”。你学会了怎么接收PS2键盘的数据,基本上也就学会了怎么驱动PS2鼠标,两者的帧格式类似,只是数据含义不同。以后如果项目中要接条码枪、接收费键盘,很多设备都支持PS2接口协议,到时候你就知道当初这份例程源码有多值钱了。
2. 硬件连接与电路设计
2.1 引脚分配:CLK和DATA接到哪个IO更合理
先看我实际测试过的一套引脚分配方案,这是大多数开发板的默认接法:
| 信号 | 51单片机引脚 | 说明 |
|---|---|---|
| CLK | P3.2(INT0) | 外部中断0输入端,下降沿触发 |
| DATA | P3.3 | 普通IO口读取 |
| VCC | +5V | PS2键盘供电 |
| GND | GND | 共地 |
选择P3.2而不是其他IO口的理由是:51单片机的外部中断0正好映射到P3.2,PS2键盘的CLK产生下降沿时,硬件自动跳转到中断服务函数,不需要主循环反复查询,实时性最好。如果不用中断,改成CLK接P1.0、DATA接P1.1,程序里死循环等待时钟跳变也可以,但处理器占用率高,不适合复杂的项目逻辑。
需要注意,P3.2和P3.3在标准51里都有第二功能(串口和外部中断相关),但作为普通IO使用时不影响。如果是STC增强型51,还有更灵活的引脚选择,但例程通常以标准89C52为基准,照着P3.2/P3.3接是最稳的。
2.2 上拉电阻和电平匹配问题
PS2键盘的CLK和DATA都是开漏输出,正常工作状态下需要外接上拉电阻到VCC,典型阻值在1k到10k之间。51单片机的P1、P2、P3口内部有上拉,但上拉能力有限,实测中如果线长超过30厘米,信号边沿会变缓,导致采样错误。这时候就体现出外部上拉电阻的重要性了。开发板上一般已经集成了4.7k或者10k的上拉电阻,如果你是自己搭的电路,务必在CLK和DATA线上各接一个4.7k电阻到+5V。
另外要注意电平匹配。现在很多51开发板用的还是5V供电,而PS2键盘本身就是5V逻辑,直接兼容。如果你用的是3.3V版单片机(比如STM32或者新出的低压51),就需要做电平转换,否则键盘输出的高电平对3.3V单片机来说可能识别不了,严重时还会倒灌电流烧坏IO口。这属于老生常谈,但每次项目里都有人栽在这上面。
2.3 接线实操:从PS2母座到单片机杜邦线
PS2接口常见的有两种:一种是6针圆形母座,一种是4针排针扩展口。6针定义里第1脚是DATA,第4脚是VCC,第5脚是CLK,第3脚是GND,剩下的第2脚和第6脚是保留位,不用管。从母座往单片机接线时,记得把金属外壳的屏蔽层接到GND,尤其是线比较长的场合,屏蔽能减少干扰。
我自己搭线的时候习惯用杜邦线和面包板先验证,确认程序正常后再做成PCB或者焊接到洞洞板上。这样分两步走的习惯能避免很多低级错误——先排除硬件问题,再优化结构。还有一点:PS2键盘的线序不同厂家可能有细微差别,拿到母座后先用万用表量一下哪根针接的是GND、哪根是VCC,千万不要看图就往上怼。
3. 软件框架与核心代码解析
3.1 数据帧格式:起始位、数据位、校验位、停止位
PS2协议每次发送11位数据:1个起始位(低电平)、8个数据位(LSB在前)、1个奇偶校验位、1个停止位(高电平)。时钟线在整个传输过程中连续输出11个脉冲,接收方在时钟的下降沿采样数据线。举个例子,如果键盘要发送通码0x1C(A键按下),二进制是00011100,LSB在前发送,实际线上看到的顺序是0,0,0,1,1,1,0,0,0(最后两位是高位)。再加上起始位、校验位、停止位,一共就是11个bit。
这就是为什么很多人第一次看PS2波形会觉得“对不上号”——因为你得先把字节按位反转,再逐位点着波形数。例程源码里通常有一段移位组装的代码,每收到一个时钟下降沿,就把DATA的电平值移到暂存字节的高位或低位,收完8个数据位之后再做反转处理。理解了这一点,整个接收逻辑就通了。
3.2 中断接收代码:不丢数据的核心
下面这段代码是例程里中断接收的核心片段,我加了详细注释:
sbit PS2_CLK = P3^2; sbit PS2_DATA = P3^3; unsigned char ps2_byte = 0; // 当前正在接收的字节 unsigned char ps2_bit_count = 0; // 已接收的位数 unsigned char ps2_buf = 0; // 完整收到的8位数据 bit ps2_ready = 0; // 一帧接收完成标志 void ps2_isr(void) interrupt 0 { unsigned char sample; sample = PS2_DATA; // 注意:在下降沿读数据线 if (ps2_bit_count > 0 && ps2_bit_count <= 8) { if (sample) { ps2_byte |= (0x01 << (ps2_bit_count - 1)); } } ps2_bit_count++; if (ps2_bit_count > 10) { // 起始位1位 + 数据位8位 + 校验位1位 + 停止位1位 = 11位 // 当计数为11时,说明一帧结束 ps2_buf = ps2_byte; ps2_ready = 1; ps2_bit_count = 0; ps2_byte = 0; } }这里最容易被忽略的是采样时机和位序。PS2协议中,键盘在CLK的低电平期间改变DATA状态,在上升沿让接收方读取最稳。但51的习惯是在下降沿进入中断,这个时刻DATA可能还在建立过程中,所以代码里在中断ISR刚进入时立即读取DATA,不要加多余的延时。如果用查询方式,就在CLK变低后延时20微秒左右再去读DATA,这个值是实践试出来的,太短读到电平不稳定,太长会错过下一拍。
3.3 通码、断码与扩展码的处理
PS2键盘发给主机的不是ASCII码,而是扫描码。扫描码分三种情况:通码(make code)表示按键按下,断码(break code)表示按键松开,前导码表示扩展按键。拿常规按键A来说,按下时发送0x1C,松开时发送0xF0 0x1C(先发0xF0再发通码)。这里的0xF0就是“断开前缀”。而右Alt、方向键这类键会多一个0xE0前缀,例如右Alt按下是0xE0 0x11,松开是0xE0 0xF0 0x11。
例程里如果只是简单显示键值,一个字节就够。但如果你要识别组合键,比如Ctrl+C、Shift+A,就必须维护一个“当前按键状态表”——收到通码时把对应位清零,收到断码时把对应位置1。这样才能知道某一时刻Shift是不是按着的,进而决定对后续扫描码做怎么样的映射。这套状态机看起来不复杂,但初学者经常栽在处理多字节序列上:0xE0和0xF0都是特殊标志位,必须缓存到状态变量里,不能当成普通键值直接显示。
3.4 键盘状态机的实现细节
我比较推荐在主循环里用“事件”的方式处理扫描码,而不是在中断里直接做复杂的逻辑。中断只负责把原始字节放进缓冲区,主循环再解析。这样做的好处是:中断服务函数尽量短,不会影响键盘的时序。拿例程来说,它通常有一个缓冲区数组,保存最近几个字节,然后主循环按“普通键 / 0xE0前缀 / 0xF0前缀”三种状态转移来解析。
伪代码逻辑如下:
unsigned char key_buffer[4]; unsigned char key_index = 0; bit last_was_e0 = 0; bit last_was_f0 = 0; void main() { while (1) { if (ps2_ready) { key_buffer[key_index] = ps2_buf; ps2_ready = 0; parse_key(key_buffer[key_index]); } // 其他任务:显示刷新、报警、通信等 } } void parse_key(unsigned char code) { if (code == 0xE0) { last_was_e0 = 1; return; } if (code == 0xF0) { last_was_f0 = 1; return; } // 如果last_was_f0为1,说明当前code是断码,可以复位状态 // 如果last_was_e0为1,说明当前code是扩展键 // 最后清标志位 last_was_e0 = 0; last_was_f0 = 0; }这里有一个关键点:0xE0和0xF0可能连续出现,比如扩展键的断码是0xE0, 0xF0, code,所以标志位的处理要小心,不能在遇到0xF0时就把E0标志清掉。例程源码中用了独立标志位而不是一个枚举状态,就是为了避免这类多字节组合的“状态爆炸”。我自己在写的时候还会加一个字节超时机制:如果收到0xE0后超过几十毫秒没有后续字节,就清掉标志,防止键盘复位或线接触不良时程序卡死。
4. 实操过程与核心环节实现
4.1 开发环境准备与工程配置
我用的是Keil C51,这是51单片机最主流的开发工具。新建工程时选择芯片型号,比如AT89C52或者STC89C52RC,然后添加一个主程序文件和一个头文件。编译选项里最重要的是开启“生成HEX文件”,因为烧录器需要HEX格式。另外留意一下晶振频率设置,如果板子上是11.0592MHz,就在Option for Target里的Xtal(MHz)填11.0592;如果是12MHz,就填12。这个参数会影响定时器初值和波特率计算,PS2实验里虽然不直接用定时器,但系统性配置别出错。
例程源码的main函数一般结构是:初始化IO口、初始化外部中断、清空显示缓冲区、然后进入死循环。初始化代码里要设置IT0=1把外部中断0设为下降沿触发,这是PS2接收的关键。有些开发板还需要设置EA=1(总中断)、EX0=1(允许外部中断0)。中断优先级不用改,默认优先级足够。
4.2 显示部分:用数码管显示扫描码
实验例程一般会配一个数码管显示模块,把收到的扫描码以十六进制形式显示出来。比如按一下A键,数码管显示“1C”,按一下B键显示“32”。原理很简单:把收到的字节拆成高四位和低四位,每个四位对应一个十六进制字符,查表转换成段码送到数码管。如果你的板子是4位数码管,还可以做成“按下显示通码,松开显示断码”的模式,这样调试时能直观看到通码和断码的完整数据流。
unsigned char code hex_table[] = { 0xC0, 0xF9, 0xA4, 0xB0, // 0 1 2 3 0x99, 0x92, 0x82, 0xF8, // 4 5 6 7 0x80, 0x90, 0x88, 0x83, // 8 9 A b 0xC6, 0xA1, 0x86, 0x8E // C d E F }; void display_hex(unsigned char val) { unsigned char h = val >> 4; unsigned char l = val & 0x0F; P0 = hex_table[h]; // 高位段码 delay_ms(5); P0 = hex_table[l]; // 低位段码 delay_ms(5); }这段代码里有一个工程细节:数码管是共阳还是共阴,直接影响段码表。我给的段码表是共阳数码管的,如果你手里是共阴,就得把所有段码取反。很多同学第一次做实验发现数码管显示的数字不对,不是程序逻辑错了,而是段码表极性搞反了。这个排查点几乎能解决80%的显示异常问题。
4.3 用LCD1602显示字符:按下就显示对应ASCII
数码管显示十六进制扫描码适合调试,真正做“键盘输入”项目时,大多数人还是愿意接一块LCD1602,直接显示字符。例程里会有扫描码转ASCII的映射表,核心思路就是把键盘扫描码作为索引,查表得到对应的ASCII字符,再送到LCD显示。
比如在标准映射表里,0x1C对应‘A’(keycode 0x1C是A键),0x1B对应‘S’,0x23对应‘D’,0x2B对应‘F’。数字键0到9则分布在0x45到0x4E,字母键则以QWERTY布局排列。实际做中文菜单的时候需要配合Shift状态去切换大小写,不加Shift就显示小写,加Shift显示大写,这个功能需要上一节说的组合键状态机支持。
LCD1602的驱动这里不多展开,例程里通常会有专门的lcd.c文件,提供lcd_init()、lcd_showchar()、lcd_showstring()几个接口。你只需要在解析到有效字符时调用显示函数,设置好显示坐标即可。
4.4 增加蜂鸣器按键反馈
实验如果只有显示,反馈感比较弱。我习惯在代码里加一个蜂鸣器反馈,每次检测到有效按键通码时让蜂鸣器响一声。实现方法是:解析到新的通码后,启动一个蜂鸣器延时(比如10毫秒),然后关闭。注意不要在中断里做延时,因为延时会阻塞PS2时钟的接收,导致后续字节丢失。正确做法是设置一个beep_tick变量,在主循环里递减,直到减到0后关蜂鸣器。
unsigned int beep_tick = 0; // 在解析到有效通码时调用 void beep(int duration_ms) { beep_tick = duration_ms; BEEP = 1; // 开蜂鸣器 } // 主循环里: if (beep_tick) { beep_tick--; if (beep_tick == 0) { BEEP = 0; // 关蜂鸣器 } }这种“非阻塞延时”的思路是单片机开发的基础课,很多初学者习惯用delay_ms()阻塞延时,一旦放在中断里或者主循环关键路径上,整个系统的实时性就崩了。例程源码能跑得稳,很大程度上就是因为这类细节处理得好。
5. 常见问题与排查技巧实录
5.1 按键没反应:先从电平开始查
这是PS2实验里最常遇到的问题。按键后数码管毫无反应,一般排查路径是:先量PS2键盘的VCC和GND是否正常,再量CLK和DATA的静态电平。正常情况下,两根信号线都应该被上拉到高电平(接近5V)。如果其中一根是低电平,很可能是上拉电阻没接或者接错了。然后按下键,用示波器或逻辑分析仪看CLK是否有脉冲。如果不方便用示波器,可以先写一个最简单的GPIO翻转程序,把CLK引脚配置成普通输入,不断读取并取反输出到另一个引脚接LED,看LED是否闪烁来间接判断是否有时钟信号。
这个查法不算“高科技”,但效率极高。很多同学一上来就把代码翻来覆去改,实际上硬件问题没有解决,代码改到天亮也没用。
5.2 显示乱码:校验位和采样时机
显示出来了但数据完全不对,比如按A显示了0xFF或者乱跳,这种情况十有八九是采样时机不对。PS2键盘的时序是:CLK下降沿时DATA已经稳定,但有些键盘在下降沿前后会有短暂的不稳定窗口。如果你的中断服务函数里延迟太久才读DATA,读到的可能是下一个bit或者毛刺。
解决方法是:进入中断后第一条语句就读取DATA,不要在中断里做任何可能耗时的工作,甚至不要调用函数。如果这样还是有误码,可以尝试在下降沿之后加一个很小的延时(比如10微秒)再采样,因为不同键盘时序存在差异,需要微调。实际项目里我习惯把读DATA和位组装的代码写成内联,避免函数调用进出栈消耗时间。
5.3 键盘能显示但无法区分按下和松开
这个问题的根源是程序没有处理0xF0断码前缀。如果你只做了一个“收到字节就显示”的功能,按下A时收到0x1C,松开时收到0xF0然后0x1C,这两个字节会被当作两次独立的按键处理,之前说的状态机派上用场了。必须在解析时判断当前字节是否为0xF0,如果是,说明下一个字节是断码,应该标记为“松开”而不是“按下”。
例程里通常会有一个结构体或者状态变量保存当前按键状态,只有通码才更新显示和蜂鸣器,断码只清理状态表里的对应位。这样按下A显示“A”,松开A不会重复显示“A”,窗口上的表现就像正常键盘一样。
5.4 长线连接时的抗干扰处理
实验台一般桌面距离到板子也就几十厘米,但如果你的项目和PS2键盘之间线长超过1米,就要考虑干扰问题。解决方法有两个方向:一是把CLK和DATA两根线用双绞线的形式绞在一起,同时让它们靠近GND走线,减少环路面积;二是在单片机端对CLK和DATA各加一个10nF左右的电容到地,滤除高频毛刺,但这会让信号边沿变缓,不是电容越大越好,小容量起步测试。
我在一次给设备键盘改装的经历中,遇到过长线接上后开机不认键盘,把线缩短到50厘米就一切正常,后来加了一级74HC14施密特触发器整形才解决。如果你不想那么麻烦,最简单的办法就是供电、时钟、数据三根线一起做屏蔽,外层屏蔽层单端接地,基本能解决90%的干扰问题。
5.5 常见问题速查表
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 完全没反应 | VCC/GND接反或未供电 | 万用表量电压 |
| CLK静态低电平 | 上拉电阻缺失或接错 | 接4.7k或10k上拉到5V |
| 数据显示乱码 | 采样时机不对、位序反转错误 | 中断首条语句读DATA,检查LSB位序 |
| 按一次显示多个字符 | 键盘处在连发状态/状态机未清标志 | 检查通码、断码的释放处理 |
| 松开后还会重复触发 | 没有识别0xF0前缀 | 完善状态机,处理断码 |
| 数码管显示段码奇怪 | 共阳共阴段码表不对 | 确认数码管类型,必要时取反段码 |
| 偶尔丢键 | 中断中有长延时/中断被屏蔽 | 缩短ISR,只在主循环做解析 |
6. 项目扩展与进阶思路
6.1 用PS2键盘实现密码锁
拿到例程源码后,很多人第一个扩展方向是密码锁。思路是把键盘输入缓冲到数组里,按下回车键时比对输入内容和预设密码。这里需要额外处理退格键(0x66)和回车键(0x5A),以及小键盘区或者字母区输入的区分。密码锁项目的难点在于“输入缓冲区的溢出保护”和“密码比对时机”,比单纯显示字符又高了一个层次。
我做这个扩展的时候,花了不少时间在“按下回车后清空缓冲区”这个细节上。如果不清空,下一次输入会把上一轮的密码残留拼接在一起,永远比对不成功。所以代码里要明确定义:输入一个字符追加到缓冲区,按下回车检查并清空,按下退格删除末尾字符,超过最大长度拒绝输入。这套逻辑放到现在做任何键盘交互产品都一样适用。
6.2 组合OS:SHIFT状态切换大小写
刚才提到的Shift组合键,实现方式比想象中简单:在状态表里给Shift键(通码0x12是左Shift,0x59是右Shift)设置一个标志位。每次收到普通键时,先查这个标志,如果为1就用大写字母映射表,为0就用小写映射表。关键是Shift键自身的通断也走同样的状态机,按下时置1,松开时清零。
这个机制还能扩展成“功能键+方向键”控制小车、控制菜单翻页等等。比如方向键UP的扫描码是0xE0 0x75,你可以在解析到E0前缀后,对后续字节判0x75,然后执行上位动作。例程源码里已经预留了E0标志位,你只需要在状态机里增加对应的处理分支。
6.3 和传感器模块联动:做一个“带键盘输入的监控终端”
51单片机课程设计里很常见的题目是温湿度检测报警系统、电磁炉简易控制这类项目。如果把PS2键盘加进去,就可以从“固定阈值报警”升级成“用户可设定阈值的交互终端”。操作逻辑可以是:按下键盘上的数字键输入目标温度,按下回车确认,按下ESC取消。这个过程中键盘显示、数码管/LCD刷新、温度传感器读取可以并行工作,正好发挥中断接收键盘数据的优势。
我觉得这是例程源码最有潜力的应用场景。因为纯传感器项目“只能看不能改”,而PS2键盘给了用户“输入”的能力,让整套系统从单向展示变成双向交互。毕设里要是能把这层逻辑讲清楚,评委印象分会高不少。
6.4 用51单片机模拟PS2主机模式
还有一种进阶玩法是角色互换:让51单片机模拟成PS2主机,主动向键盘发送控制命令,比如启用/禁用NumLock指示灯、请求键盘发送设备ID等。这需要向CLK线主动拉低至少100微秒来暂停键盘通信,然后往DATA线上写入命令字节,再释放CLK让键盘接收。PS2协议中主机向设备发送数据时,数据的改变发生在CLK低电平,设备在CLK上升沿采样,方向和键盘到主机正好相反。
这个玩法已经把PS2协议理解得很深了。虽然对课程设计可能用不上,但如果你打算做键盘转接器或者键盘测试工具,这是必经之路。例程源码里没有这部分,不过基于给你看的接收代码反推,主机模式只是把读改成写,结构类似。
最后的操作体会
讲真,PS2键盘实验在51单片机例程源码里属于那种“不起眼但非常耐嚼”的项目。整份代码量不大,原理也不复杂,但它把中断、时序、状态机、串行协议这些嵌入式开发的基本功全串起来了。我建议你拿到例程后不要只烧录跑通就完事,把CLK和DATA的波形用逻辑分析仪完整抓一遍,看着11个脉冲如何在示波器上流动,键盘协议就真正变成你自己的基本功了。
如果你刚做完这个实验,下一步试试把例程里的中断接收改成查询方式,观察两种方式在运行其他任务时的区别;再把状态机从“通码断码处理”扩展到“E0扩展码处理”。这么折腾一遍之后,我看好你直接就能上手做更复杂的单片机交互项目。
本文还有配套的精品资源,点击获取