很多人在做单片机课程设计或毕业设计时,会先翻开发板资料包,看到什么芯片就选什么方案。但如果你已经决定做“自动售货机”这个题目,又担心普通投币方案太老套、容易被答辩老师追问得无话可说,那我建议你认真看一下“51单片机 + GSM短信模块”这种组合。它没有破坏自动售货机本身的功能完整性,却把系统的交互边界从“现场按键”扩展到了“远程通知”,整个项目的技术含量和可展示性都会往上走一档。
这篇文章会围绕“基于51单片机的GSM自动售货机”从原理、硬件选型、代码实现到调试排错完整拆解。我会尽量避开纯理论堆砌,把重点放在你真正会在实验室里遇到的细节上,比如LCD1602怎么显示余额、投币逻辑怎么设计、SIM900A模块为什么发送短信不稳定、AT指令返回“ERROR”时先查哪几个点。读完之后,你至少能自己搭出一个能跑通“投币—选商品—出货—发短信通知”的完整演示样机。
1. 这篇文章真正要解决的问题
传统自动售货机常见的方案是“投币器 + 单片机 + 电机出货”。投币器识别硬币后,单片机收到脉冲信号,然后根据用户按键选择执行对应货道的电机。这种方案本身没有错,但它有两个很现实的问题:
第一,运营者无法远程知道机器状态。机器放在教学楼一楼,晚上缺货了、卡货了、或者被断电了,你不可能守在旁边,只能等用户扫码投诉或定期跑过去查看。如果是课程设计,答辩老师大概率会问:“你如何知道机器需要补货?”没有远程模块,这个问题很难回答得漂亮。
第二,纯投币方案在功能上偏静态。用户只能投币、按键、取货,整个交互过程是单向的。引入GSM模块之后,系统可以在关键事件发生时主动发送短信给管理员:比如“某货道已售罄,请补货”“当前销售额达到XX元”“设备被非法震动”。这就把一台单纯的售货设备变成了一个具备基础物联网特征的终端。
这里要澄清一个容易混淆的判断:51单片机本身没有操作系统,不能直接上网,但GSM模块相当于一个“手机通信网关”。单片机通过串口发送AT指令,GSM模块把文字内容以短信形式发送到指定手机号。整个过程不需要宽带、不需要路由器,只要有手机信号就能工作,非常适合校园、商场、景区等场景的演示和原型验证。
所以这篇文章要解决的核心问题不是“51单片机怎么点亮一个LED”,而是:在51单片机资源非常有限的条件下,如何把显示、按键、电机出货、串口通信、短信发送几个模块在同一个任务循环里有条不紊地跑起来。很多人项目做不通,不是单个模块不会调,而是这几个模块组合在一起时,时序、电平、串口占用的冲突没有处理好。下面我会按照实际开发顺序逐步展开。
2. 核心概念:51单片机、GSM模块与自动售货机控制逻辑
2.1 51单片机:经典、廉价、教学价值高
51单片机通常指Intel 8051内核的兼容芯片,国内最常见的是STC89C52系列。它集成了CPU、RAM、ROM、定时器、串口、GPIO等基本资源。虽然主频不高(通常12MHz或11.0592MHz)、RAM也只有256字节左右,但驱动LCD1602、独立按键、直流电机、SIM900A这类外设完全够用。
自动售货机用到的主要资源如下:
- 定时器0/1:提供延时基准和串口波特率。
- 串口UART:和GSM模块通信。
- GPIO:控制LCD1602数据线、电机驱动引脚、按键检测。
51单片机的优点是教材多、例程序多、焊接调试门槛低。缺点同样明显:没有操作系统,任务调度靠大循环+中断,串口同时收发短信时要格外小心缓冲区溢出。但如果你要做课程设计,51恰恰是最不容易在答辩时被质疑“不是你自己做的”的芯片。
2.2 GSM模块:短信通信的关键设备
GSM(Global System for Mobile Communications,全球移动通信系统)模块本质是一个完整的手机通信基带处理器,通过串口和单片机通信。常用型号是SIM900A、SIM800C。模块上电后,需要插入一张能正常收发短信的SIM卡(建议用小流量或无流量的基础套餐卡),并通过AT指令控制。
要理解GSM模块在售货机项目里的角色,可以做一个类比:它相当于一个“微型手机”。你给这个手机发送“AT+CMGS\r\n”,它就进入短信编辑状态;你继续发送内容,再发送十六进制的1A结束符,它就把短信发出去。单片机是大脑,而GSM模块是嘴和耳朵。
值得注意的事:SIM900A上电瞬间电流峰值可达2A,如果用USB转TTL供电,很容易电压跌落导致模块反复重启。所以实际项目中,GSM模块必须单独用5V/2A以上电源供电,或者使用稳压模块,不能和单片机共用一个USB口供电。这个细节是很多新手项目失败的真正原因。
2.3 自动售货机的核心控制逻辑
自动售货机的控制逻辑可以分成四层:
- 人机交互层:LCD1602显示商品名称、单价、投币余额;矩阵键盘或独立按键选择商品和模拟投币。
- 业务逻辑层:判断余额是否足够,扣减余额,解锁货道,触发电机转动。
- 执行层:继电器或电机驱动模块控制直流电机或舵机,把商品推落到取货口。
- 通信层:在指定事件发生时,通过GSM模块发送短信到管理员手机。
在51单片机这种裸机环境下,逻辑层一般放在while(1)循环里顺序扫描。按键需要消抖,显示刷新不能卡顿,电机转动需要定时停止,短信发送不能阻塞主循环太久。这些约束决定了代码不能简单地按顺序“先做A再做B”,而要设计成一个状态机或事件标志驱动的结构。后面我会给出一个典型的实现思路。
3. 系统总体架构与硬件选型
3.1 系统架构图
从逻辑上看,整个系统可以画成以下对应关系:
[独立按键/矩阵键盘] → [51单片机] → [LCD1602显示] ↑ │ └── 投币信号 ┌──┴──┐ [电机驱动] → [货道出货] [GSM模块] → [短信通知管理员]单片机是核心处理器,按键负责投币和选择,LCD1602负责信息反馈,电机驱动实现出货动作,GSM模块负责把售货机的关键事件通过短信发送给管理员。
3.2 硬件清单
下面是一个比较完整的物料清单,表格中标明了模块在系统里的作用:
| 模块 | 型号/规格 | 作用 | 注意事项 |
|---|---|---|---|
| 主控芯片 | STC89C52RC | 核心控制器 | 和8051指令兼容 |
| 显示模块 | LCD1602 | 显示商品名、单价、余额 | 需要1602的驱动字库 |
| 按键 | 独立按键或4x4矩阵键盘 | 模拟投币、选择商品 | 按键必须消抖 |
| 出货执行 | 直流电机+驱动板,或SG90舵机 | 推动商品下落 | 使用电机驱动模块防止电流倒灌 |
| 通信模块 | SIM900A/SIM800C | 发送短信通知 | 独立供电,天线要装好 |
| 电源 | 5V/2A以上适配器 | 给单片机、电机、GSM供电 | GSM峰值电流大 |
| 商品模型 | 小瓶装饮料/3D打印货道 | 模拟真实出货 | 展示效果好即可 |
如果学校预算有限,电机可以用SG90舵机代替,舵机转动一定角度推动挡板,结构更简单。不过舵机需要PWM信号,51单片机没有硬件PWM也能用定时器模拟,代码会稍微复杂一些。本文章节以直流电机驱动为例。
3.3 模块接线规划
在写代码之前,必须先规划好引脚。下面是我常用的一组引脚分配,你可以按自己的开发板修改:
// 引脚分配示例 sbit RS = P2^6; // LCD1602 寄存器选择 sbit RW = P2^5; // LCD1602 读写选择 sbit EN = P2^7; // LCD1602 使能信号 #define LCD_DATA P0 // LCD1602 8位数据总线 sbit KEY_ADD = P3^2; // 投币按键(模拟1元投币) sbit KEY_BUY = P3^3; // 确认购买按键 sbit MOTOR_PIN = P1^0; // 电机控制引脚 sbit LED_STATE = P1^1; // 状态指示灯,方便调试GSM模块和单片机使用串口连接:单片机TXD(P3.1)接模块RXD,单片机RXD(P3.0)接模块TXD,然后共地。注意,SIM900A的TTL电平标准比51单片机宽,但为了稳定,多数模块板已经做了电平转换,接上就能用。如果模块没有电平转换,建议使用MAX232或直接换带电平转换的模块,不要随手把5V和3.3V混接。
4. 环境准备与开发工具
开发51单片机项目不需要复杂的集成环境,下面是我推荐的软件组合:
| 工具 | 作用 | 说明 |
|---|---|---|
| Keil C51 | 编写和编译C语言代码 | 最常用的51开发IDE |
| STC-ISP | 烧录程序到STC芯片 | 官方提供串口下载软件 |
| 串口调试助手 | 调测GSM模块AT指令 | 也可以用SecureCRT |
| 万用表 | 检查电压、通断 | 排查硬件故障必备 |
使用Keil C51时,建议新建一个空工程,选择芯片型号为STC89C52RC或Atmel AT89C52。由于STC系列芯片内部有硬件选项,比如外部晶振、复位电路,如果使用STC-ISP烧录,需要在烧录界面选择外部晶振或内部IRC。
GSM模块调试有一个很重要的前置步骤:先把SIM900A模块插上SIM卡、接上电源和USB转TTL,然后用串口调试助手发送“AT\r\n”,如果返回“OK”,说明模块已经工作。如果没有返回,先检查电源是否足够、SIM卡是否插好、天线是否拧紧。这个验证一定要在连接单片机之前完成。否则你后面无法判断是单片机程序的问题还是GSM模块本身的问题。
5. 核心代码实现
这一部分给出可以直接编译验证的核心代码框架。为了让代码结构清晰,我按文件功能拆分成几个代码块。你可以把驱动函数放在一个.c文件里,也可以全部放在main.c中,根据个人习惯决定。这里给出的版本尽量精简,重点展示关键逻辑。
5.1 LCD1602显示驱动
LCD1602是字符型液晶,内部有字符库,我们只需要发指令和数据即可显示ASCII字符和常用符号。下面是基础驱动,包含初始化、写命令、写数据、显示字符串和清屏。
// 文件:lcd1602.c #include <reg52.h> #include <string.h> sbit RS = P2^6; sbit RW = P2^5; sbit EN = P2^7; #define LCD_DATA P0 void LCD_Delay(unsigned int t) { unsigned int i; while (t--) { for (i = 0; i < 100; i++); } } void LCD_WriteCmd(unsigned char cmd) { RS = 0; RW = 0; EN = 0; LCD_DATA = cmd; LCD_Delay(1); EN = 1; LCD_Delay(1); EN = 0; } void LCD_WriteData(unsigned char dat) { RS = 1; RW = 0; EN = 0; LCD_DATA = dat; LCD_Delay(1); EN = 1; LCD_Delay(1); EN = 0; } void LCD_Init(void) { LCD_WriteCmd(0x38); // 8位数据,2行显示,5x7点阵 LCD_WriteCmd(0x0C); // 显示开,光标关,闪烁关 LCD_WriteCmd(0x06); // 写入后光标自动右移 LCD_WriteCmd(0x01); // 清屏 } void LCD_Clear(void) { LCD_WriteCmd(0x01); } void LCD_ShowString(unsigned char row, unsigned char col, char *str) { unsigned char addr; if (row == 0) { addr = 0x80 + col; } else { addr = 0xC0 + col; } LCD_WriteCmd(addr); while (*str != '\0') { LCD_WriteData(*str); str++; } }LCD1602在写指令之前必须确认模块已经完成上电初始化。有些开发板使用的是慢速单片机,初始化指令的时间间隔也要符合LCD1602的时序要求(一般十几毫秒即可)。如果屏幕显示“花屏”或者全是方块,优先检查电源电压和RS、RW、EN三条控制线是否接反,尤其注意EN信号高低电平是否触发在正确的沿。
5.2 按键扫描与投币逻辑
自动售货机的投币逻辑不复杂,但需要注意状态保存。我在这里使用一个全局变量balance表示当前余额,单位是“角”,投币按键每按一次增加余额,同时刷新LCD。购买逻辑则是判断余额是否大于等于商品价格,如果满足就减扣余额并触发电机。
// 文件:vending_machine.c #include <reg52.h> #include "lcd1602.h" sbit KEY_ADD = P3^2; sbit KEY_BUY = P3^3; sbit MOTOR_PIN = P1^0; unsigned int balance = 0; // 当前余额,单位:角 unsigned int price = 3; // 商品单价,对应3元,单位:角 unsigned char KeyScan(void) { if (KEY_ADD == 0) { delay_ms(20); while (KEY_ADD == 0); return 1; } if (KEY_BUY == 0) { delay_ms(20); while (KEY_BUY == 0); return 2; } return 0; } void Motor_On(void) { MOTOR_PIN = 1; delay_ms(800); // 电机运行0.8秒,推动商品掉落到取货口 MOTOR_PIN = 0; } void ProcessKey(void) { unsigned char key = KeyScan(); switch (key) { case 1: balance = balance + 10; // 每按一次增加1元 break; case 2: if (balance >= price) { balance = balance - price; Motor_On(); LCD_Clear(); LCD_ShowString(0, 0, "SALES OK!"); delay_ms(1000); } else { LCD_Clear(); LCD_ShowString(0, 0, "NOT ENOUGH"); delay_ms(1000); } break; default: break; } LCD_Clear(); LCD_ShowString(0, 0, "BALANCE:"); LCD_ShowString(0, 9, " "); LCD_ShowChar(0, 9, balance / 100 + '0'); LCD_ShowChar(0, 10, balance / 10 % 10 + '0'); LCD_ShowChar(0, 11, '.'); LCD_ShowChar(0, 12, balance % 10 + '0'); }这里我把余额设计成整数“角”,显示的时候再转换成“元.角”,避免使用浮点数,因为51单片机做浮点运算既慢又占ROM。购买成功后,通过GSM发送短信通知管理员的调用可以放在Motor_On()之后,这一步我会在下一小节实现。
5.3 GSM模块发送短信的实现
GSM模块发送短信是串口命令交互过程。51单片机通过串口发送AT指令,然后解析模块返回值。最简单的方式是不解析返回值,直接延时后发送下一条指令,适合演示;工程上更推荐按返回的“OK”或“ERROR”状态机跳转。
这里给出一个易读的发送短信函数,使用串口字符串发送:
// 文件:gsm.c #include <reg52.h> void UART_Init(void) { SCON = 0x50; // 8位数据,可变波特率 TMOD &= 0x0F; TMOD |= 0x20; // 定时器1工作在方式2 TH1 = 0xFD; // 波特率9600,晶振11.0592MHz TL1 = 0xFD; TR1 = 1; ES = 1; EA = 1; } void UART_SendString(char *str) { while (*str != '\0') { SBUF = *str; while (TI == 0); TI = 0; str++; } } void GSM_SendSMS(char *phone, char *msg) { // 1. 设置短信格式为文本模式 UART_SendString("AT+CMGF=1\r\n"); delay_ms(500); // 2. 发送短信命令 UART_SendString("AT+CMGS=\""); UART_SendString(phone); UART_SendString("\"\r\n"); delay_ms(500); // 3. 发送短信内容 UART_SendString(msg); // 4. 发送十六进制结束符 0x1A SBUF = 0x1A; while (TI == 0); TI = 0; delay_ms(1000); }如果模块工作正常,调用GSM_SendSMS("13800138000", "Vending3 out of stock!")就能把短信发出去。这里有几个关键点需要解释:
AT+CMGF=1是把GSM模块切换到文本模式,否则默认可能是PDU模式,中英文内容处理完全不同。AT+CMGS="手机号"后面的\r\n必须完整,不能只写\n。- 短信内容结束必须发送十六进制的
0x1A,相当于键盘上的Ctrl+Z,表示“短信内容输入结束,可以发送了”。 - 每一步之间建议加延时,因为GSM模块返回“OK”需要时间。演示项目里用固定延时最简单,如果想做得更可靠,可以解析串口接收到的“OK”字符串。
5.4 主函数整合
主函数把上面几个模块整合到一个循环里。基本流程是:初始化LCD → 初始化串口 → 显示初始界面 → 循环扫描按键。每次售货成功,除了出货和扣款,还触发一次短信通知。
// 文件:main.c #include <reg52.h> #include "lcd1602.h" #include "vending_machine.h" #include "gsm.h" void main(void) { unsigned char key; unsigned int salesCount = 0; LCD_Init(); UART_Init(); LCD_ShowString(0, 0, "VENDING MACHINE"); LCD_ShowString(1, 0, "BALANCE:"); LCD_ShowString(1, 9, "0.0"); while (1) { key = KeyScan(); if (key == 1) { balance = balance + 10; LCD_Clear(); LCD_ShowString(0, 0, "BALANCE:"); // 刷新显示余额,这里可调用显示函数 } if (key == 2) { if (balance >= price) { balance = balance - price; Motor_On(); salesCount++; LCD_Clear(); LCD_ShowString(0, 0, "SALE OK!"); // 发送短信通知管理员 GSM_SendSMS("13800138000", "Vending: A product was sold."); } else { LCD_Clear(); LCD_ShowString(0, 0, "NOT ENOUGH"); } delay_ms(1000); LCD_Clear(); LCD_ShowString(0, 0, "VENDING MACHINE"); } } }这段代码里delay_ms函数没有在示例中展开,你可以在工程里定义基于定时器或空循环的软件延时。对于课程设计来说,空循环延时已经足够;如果要精确控制电机时间,建议用定时器中断计时,避免主循环被网络或者短信阻塞时电机会失控。
5.5 关于中断和串口接收的补充
虽然上面的GSM发送函数只用了发送,没有做接收解析,但在实际项目中最好开启串口接收中断,把GSM模块返回的“OK”“ERROR”等状态存到缓冲区,主循环通过标志位判断是否继续下一步。这样能极大提高稳定性,尤其是连续发短信时,不会因为模块处理不及而导致AT指令粘连。
下面给一个最简单的串口接收中断框架,用于接收“OK”字符串:
// 串口接收中断示例 unsigned char rxBuffer[32]; unsigned char rxIndex = 0; bit okFlag = 0; void UART_ISR(void) interrupt 4 { unsigned char ch; if (RI) { RI = 0; ch = SBUF; rxBuffer[rxIndex++] = ch; if (rxIndex >= 32) rxIndex = 0; if ((rxIndex >= 2) && (rxBuffer[rxIndex - 2] == 'O') && (rxBuffer[rxIndex - 1] == 'K')) { okFlag = 1; rxIndex = 0; } } }用这个方式,主循环可以等待okFlag再发送下一条AT指令,避免固定延时的不确定性。这是GSM模块通信里最值得优化的地方,也是答辩时一个不错的加分点。
6. 运行结果与效果验证
6.1 编译与烧录
在Keil中按下F7编译,确认0 Error。然后打开STC-ISP,选择对应芯片型号,打开生成的hex文件,点击下载,给单片机重新上电。烧录成功之后,LCD1602会显示“VENDING MACHINE”和“BALANCE:0.0”。如果LCD没有显示,不要急着改代码,先用万用表检查电源和LCD的对比度可调电阻。
6.2 功能测试流程
建议按下表逐项验证,不要一上来就测试GSM短信,因为GSM模块不稳定时排查范围会很大。
| 测试项 | 操作 | 预期现象 |
|---|---|---|
| LCD显示 | 上电 | 两行内容正常显示,无乱码 |
| 投币按键 | 按KEY_ADD | 余额增加并刷新 |
| 余额不足购买 | 按KEY_BUY | 显示“NOT ENOUGH” |
| 正常购买 | 先投币再按KEY_BUY | 电机转动,余额扣除,显示“SALE OK” |
| GSM发送短信 | 调用GSM_SendSMS | 管理员手机收到短信 |
当电机转动测试通过之后,再接上GSM模块,完成最后一次短信通知测试。这样如果短信失败,至少能确定不是电机或按键的问题。
6.3 判断GSM模块是否正常工作
如果发送短信失败,先不要看单片机代码,用USB转TTL直接连接GSM模块,在串口调试助手里手动输入:
AT然后按回车,期望返回:
OK如果这一条都不通过,说明模块供电、SIM卡、天线、串口接线至少有一项有问题。大部分GSM模块发送短信失败的案例,都出在电源供电不足上。SIM900A模块在发短信时需要较大电流脉冲,电压一旦跌到3.4V以下就会自动关机或返回“ERROR”。解决方法是换5V/2A以上的独立电源,并且电源线要尽量短。
7. 常见问题与排查思路
下面表格总结了我在实际调试中最常遇到的几个问题,基本覆盖了新手从硬件到软件的主要坑点。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| LCD1602不显示 | 对比度电阻未调好或接线错误 | 万用表检查电压;调节V0引脚电压 | 调整到V0约0.5V~1V;重新检查RS/RW/EN接线 |
| 按投币按键余额不变 | 按键抖动或GPIO引脚定义不对 | 串口打印或LED观察 | 检查sbit引脚是否和电路一致;增加消抖延时 |
| 电机不转 | 驱动电流不足 | 测量电机供电电压 | 使用ULN2003或L298N驱动,不用GPIO直连 |
| GSM模块上电无反应 | 电源功率不够 | 观察模块指示灯是否闪烁后熄灭 | 更换5V/2A电源,检查天线和SIM卡 |
| 发送短信返回ERROR | 短信中心号码问题或信号弱 | 串口发送AT+CSQ查信号质量 | 如果CSQ值为0或99,说明信号差,换个位置或加天线 |
| 发送PDU乱码 | 使用文本模式时未设置AT+CMGF=1 | 手动串口调试 | 每条指令前设置文本模式 |
有几个容易被忽视的细节,我再单独说明一下。
第一,SIM卡。最好是剪好的标准SIM卡,不能是停机卡。如果你用的是物联网卡,注意是否支持短信业务,很多物联网卡默认只支持流量,不支持短信。
第二,短信中心号码。普通电话卡一般插卡后会自动读取短信中心号码,不需要手动设置。但如果你发现模块返回“OK”却一直收不到短信,可用AT+CSCA?查询短信中心号码,确认为空时手动设置。
第三,共地。单片机和GSM模块必须共地,否则串口收到的数据会乱码。这几乎是所有串口外设的通用要求。
8. 最佳实践与工程建议
前面把功能跑通,课程设计分数已经不错了。但如果想让代码质量再上一个台阶,下面几条建议很有价值。
8.1 代码架构:把功能拆成独立模块
不要把LCD驱动、按键、电机、GSM的所有代码全部堆在main.c里。建议按文件拆分为:
src/ ├── main.c ├── lcd1602.c ├── vending_machine.c ├── gsm.c └── delay.c每个模块只暴露必要的函数接口,例如LCD_Init()、GSM_SendSMS()、Motor_On()。这样做的好处是,答辩时老师追问某个细节,你能快速定位到对应文件,而不是在一千多行的main.c里翻找。
8.2 状态机改造
现在的示例代码是线性的,实际项目中如果并发事件多,推荐设计一个轻量状态机。比如状态包括:“空闲”“投币中”“出货中”“短信发送中”。每次主循环扫描当前状态,根据事件跳转。这样做可以降低电机和短信同时出现时互相干扰的概率,也为以后增加多个货道留出扩展空间。
8.3 GSM通信可靠性
短信模块的通信不是百分之百可靠的。工程上建议:
- 每次AT指令之间增加状态机等待“OK/ERROR”后,再发下一条指令。
- 短信发送失败时,允许设置重发次数上限(比如3次),不要死循环。
- 短信内容尽量简短,中文字符在文本模式下可能乱码,建议使用英文或拼音,或者改用PDU模式发送中文。
- 生产环境建议使用4G Cat.1模块替代2G GSM模块,因为国内部分运营商已经逐步减少2G网络覆盖。
8.4 硬件设计注意事项
电机必须经过驱动模块或三极管,不能直接把电机接在51单片机GPIO上。51单片机的GPIO灌电流能力有限,驱动电机时电流可能达到几百毫安甚至更大,轻则电机抖动不转,重则烧坏IO口。
另外,GSM模块复位信号、电源指示灯这些引脚,建议预留测试点。接插件要选方便插拔的,不要焊死,因为调试时你大概率需要多次插拔SIM卡和天线。
8.5 安全与合规提醒
GSM模块和短信功能是合法的远程通信应用,但使用时必须注意:SIM卡必须是本人或实验室合法取得的号码,不能用于发送垃圾短信、骚扰短信或从事其他违法用途。课程设计演示时,建议使用自己的手机号或实验室专门配发的测试卡。涉及短信发送的代码,也要做好发送频率限制,避免因程序bug导致模块反复发送短信,造成不必要的费用和影响。
9. 总结与后续学习方向
基于51单片机的GSM自动售货机是一个典型的多模块协同项目,它涵盖了单片机开发中最常见的几个知识点:GPIO控制、定时器、外部中断、串口UART、LCD显示、电机驱动以及AT指令通信。如果你能把这样一个项目完整跑通,说明你对51单片机的理解已经不只是“点灯”级别了。
从输入材料可以看出,这篇博客贴合“51单片机课程设计”和“GSM远程通知”两个关键搜索方向。如果你正在准备课程设计或毕业设计,建议先按文章里的步骤把基础版调通,再往下面几个方向扩展:
- 增加多个货道,用矩阵键盘选择不同商品,不同货道对应不同电机引脚。
- 用DS1302或DS18B20加入时间显示和环境温度检测,让系统信息更丰富。
- 把GSM模块换成4G Cat.1模块,通过MQTT协议接入云平台,实现真正的物联网远程管理。
- 用数码管或OLED代替LCD1602,降低显示模块的驱动难度。
最后提醒一句:做这种嵌入式综合项目,难点往往不在某个单独模块的例程,而在于模块之间的衔接。所以一定要按“先显示、再按键、再电机、最后GSM”的顺序推进,每完成一步就验证一步。只要主线不断,最终呈现出来的系统一定能在答辩或展示现场讲出完整故事。建议收藏这篇文章,调试时对照着排查,会少走不少弯路。