
简介一套面向51单片机入门与课程设计的直流电机控制方案涵盖PWM加减速、启动/急停及高温报警功能配合Proteus完成仿真能够帮助电子类专业学生或爱好者快速掌握单片机定时器/PWM、按键处理与DS18B20温度检测的综合应用。资源包共43个文件大小约954KB主要包含C语言源程序、头文件、可烧录的hex文件、Proteus仿真工程、原理图文档、元件清单表格、流程图及若干效果截图从代码到电路图均有覆盖。当前已有356人下载学习适合作为课程设计、毕业设计或自学实践参考。资料中提供完整的源代码与仿真环境附带了原理图、物料清单和可视化流程图便于对照硬件连接和程序逻辑进行调试也节省了自行绘制与整理的时间尤其适合需要快速获得可运行原型的学习者。1. 基于51单片机的直流电机项目真正的工作量在“加减速”和“温度PWM”两个词里打开 Proteus 仿真文件想让直流电机转起来只需要一个电源和一根信号线10 分钟就能看到旋转。但同一套题目里加上“加减速”和“温度PWM”性质就变了加减速不是给电机的电压跳变而是 PWM 占空比按按键平滑增减温度PWM则意味着 DS18B20 测到的温度偏差要反过来修正占空比让电机转速既受手动控制又被温度参数自动补偿。这是 51 单片机课程设计里最典型的闭环组合把开环调速、单总线测温、Proteus 原理图和仿真图验收串成一条完整链路。下面按硬件选型、PWM 生成、温度闭环、仿真验收四条线展开参数可以直接抄边界也一并说明。2. 硬件链路与器件选型原理图里电流路径先于代码硬件设计的顺序应该是先定电流路径再写配置代码。原理图上要能一眼看出三块回路——最小系统、PWM 电流放大级、温度采集输入级。把这条路径画清楚后面写代码才有依据。2.1 51单片机最小系统晶振频率决定 PWM 时间基准STC89C52RC 和 AT89C51 在 Proteus 里的仿真行为一致都可以当主控。晶振选 12MHz 而不是 11.0592MHz原因是机器周期正好是 1us定时器初值可以直接心算12MHz / 12 1MHz一个机器周期 1us。若题目后续要加串口通信那时再换 11.0592MHz 去凑标准波特率纯做 PWM 调速用 12MHz 更顺手。复位电路用 10uF 电解电容接 VCC、10k 电阻接地RC 时间常数约 100ms能保证上电复位可靠。这里有个容易漏的点P0 口是开漏输出如果原理图里接了两位共阴数码管显示温度和占空比必须给 P0 加 10k 排阻上拉否则段码电流不够数码管亮度不均甚至不亮。Proteus 里不加上拉也能侥幸跑通实物上会直接翻车。2.2 电机驱动选型Proteus 用 ULN2003实物再考虑 L298NULN2003A 是达林顿管阵列在 Proteus 元件库里直接搜 IN1 到 IN7 就能找到不需要加载任何第三方模型这是它在这个题目里的最大价值。接法也很固定单片机 P1 口接 ULN2003 的输入脚输出脚是集电极开路直流电机一端接 VCC、另一端接输出脚。这样 P1 口只出毫安级控制电流电机的大电流走外部 5V 电源不会回头灌进单片机。驱动方案是否支持正反转Proteus 自带模型实物成本适用场景ULN2003A否自带直接可用约 2 元单向加减速Proteus 仿真的默认选择L298N是需额外加载库文件约 15 元实物要求正反转的完整 H 桥方案TB6612是需额外加载库文件约 10 元对 PWM 频率和噪声更敏感的小车既然标题只写了加减速没有提正反转ULN2003 在成本和仿真通过率上都是最优解。L298N 的特点是 ENA 引脚要单独输入 PWMENB 控制另一路Proteus 里若模型加载不对会出现使能脚电平正确但电机不转的情况答辩演示时很尴尬。选型上我给的建议是仿真文件固定用 ULN2003实物想换 L298N 时只需要改驱动板接线代码不用动。2.3 DS18B20 温度传感器上拉电阻与寄生供电DS18B20 是单总线器件数据脚 DQ 必须接一个 4.7k 上拉电阻到 VCC。Proteus 仿真模型对这一点的宽容度比实物高很多不加也能读出温度但原理图作为设计文档必须把 4.7k 画上否则交付时会被问“这个电阻为什么没有”。接法上DQ 接 P3.7VCC 接 5VGND 接地。需要注意的是 DS18B20 支持寄生供电模式即 DQ 在特定时序里兼作电源但课程设计里直接外部供电稳定性最好不要为省一根线去用寄生模式仿真和实物行为会有差异。上拉电阻的取值也不是随便定的4.7k 在 5V 下提供约 1mA 上拉电流满足单总线 15us 时隙的上升沿要求换成 10k 也能工作但线缆稍长时波形边沿会变缓误码率上升。3. 加减速的产生定时器中断生成可调占空比 PWMPWM 是这个项目的核心输出也是答辩时最容易被抓着问细节的部分。原理上直流电机转速正比于电枢两端平均电压PWM 通过固定频率下改变高电平占比来改变平均电压。加减速的本质就是改变这个占比。3.1 为什么 Proteus 仿真不用 STC89C52 的硬件 PCASTC89C52 内部有 PCA 模块配置 CCAPM0、CCAP0H 后可以硬件输出 PWM不占 CPU。但 Proteus 自带的 AT89C51/AT89C52 仿真模型并不完整支持 STC 增强型寄存器CCAPM0 这个地址在模型里没有对应行为填写了也不会产生波形。所以 Proteus 仿真必须退回定时器软件模拟 PWM这是这类项目里第一个隐性坑。实物烧录时如果换成 STC89C52可以再启用硬件 PCA 省出 CPU但仿真文件和实物代码要保持一致才能保证验收时两端行为可对照。3.2 定时器0方式210us 中断与 100 级占空比软件模拟 PWM 需要同时满足两个参数PWM 频率和占空比级数。它们的关系是定时器溢出周期 PWM 周期 / 级数。以 1kHz PWM、100 级占空比为例定时器必须每 10us 中断一次12MHz 晶振下机器周期 1us定时器0 方式2 初值 256 - 10 0xF6。这样电机的通电时间被切成 100 份占空比步进 1%加减速手感足够平滑。参数数值计算依据晶振频率12MHz机器周期 1us定时器0工作方式方式28位自动重装TH0 与 TL0 相同无需重复赋值定时初值0xF6256 - 10us 246 0xF6PWM 级数100 级counter 从 0 计到 99PWM 频率约 1kHz10us x 100 1ms注意中断服务程序的现场保护会额外占用约 2-3us实际 PWM 频率会落在 950-1000Hz 之间Proteus 虚拟示波器测到的是实际值不是理论值。若想提高 PWM 频率到 10kHz每个级别只剩 1us定时器初值 0xFF 没有余量中断出入栈抖动会直接造成占空比不均匀所以这个方案在 12MHz 晶振下做到 1kHz 就是合理边界。3.3 按键加减速与占空比限幅逻辑三个按键分别承担加速、减速、模式切换。加减速的粒度取 1%长按连续加也是同样的逻辑只是每 100ms 再执行一次。占空比不能到 0% 和 100%0% 时电机停转PWM 波形消失示波器上无法判断系统是死机还是正常输出100% 时电机满压运行失去 PWM 调速意义且 ULN2003 的功耗会明显上升。限幅范围取 5% 到 95%这就是软件上的“死区保护”。3.4 源代码PWM 输出与按键调速最小实现#include reg52.h sbit PWM_OUT P1^0; // PWM输出接ULN2003输入 sbit KEY_UP P3^2; // 加速按键 sbit KEY_DOWN P3^3; // 减速按键 unsigned char counter 0; // PWM级数计数器 0-99 unsigned char pulse 50; // 当前占空比 5-95 void Timer0_Init(void) { TMOD 0xF0; // 只改低4位保留定时器1配置 TMOD | 0x02; // 定时器0方式28位自动重装 TH0 0xF6; // 初值24610us中断 TL0 0xF6; ET0 1; // 使能定时器0中断 TR0 1; // 启动定时器 EA 1; // 开总中断 } void Timer0_ISR(void) interrupt 1 { counter; if (counter 100) counter 0; if (counter pulse) PWM_OUT 1; // 前pulse个时隙输出高 else PWM_OUT 0; // 后续时隙输出低 } void Key_Scan(void) { static unsigned char key_delay 0; if (!KEY_UP) { key_delay; if (key_delay 10) { // 约100ms消抖 if (pulse 95) pulse; // 加速限幅上限95 key_delay 0; } } else if (!KEY_DOWN) { key_delay; if (key_delay 10) { if (pulse 5) pulse--; // 减速限幅下限5 key_delay 0; } } else { key_delay 0; } } void main(void) { Timer0_Init(); while (1) { Key_Scan(); } }逻辑说明定时器0每 10us 中断一次counter 从 0 到 99 循环一周就是 1ms即 1kHz PWM 周期。pulse 是阈值counter 小于 pulse 时输出高反之输出低。pulse50 时高电平占 50 个时隙、低电平占 50 个时隙占空比正好 50%。按键消抖没有用独立定时器而是借用主循环的扫描间隔叠加计数这种写法在 PWM 项目里足够稳定也不会额外占用定时器资源。参数说明TMOD 0xF0 是为了不影响定时器1 的配置如果代码里只用了定时器0也可以直接写 TMOD 0x02。pulse 的初始值 50 对应上电即半速方便答辩演示时先看到转动再调速。限幅 5 和 95 必须写在加减逻辑里不能让 pulse 越界后 counter pulse 的比较产生异常波形。4. 温度闭环DS18B20 读数如何修正占空比温度 PWM 的含义是把 DS18B20 测到的温度作为反馈量温度升高时占空比自动增大电机转速上升带动风扇或散热结构降温。这是一个简单的比例控制回路偏差越大修正量越大最后用限幅保证安全。4.1 单总线时序为什么在 Proteus 里更容易踩坑DS18B20 的复位脉冲、写时隙、读时隙都是微秒级时序Proteus 仿真时 CPU 执行速度比实物快延时函数经常出现“仿真能跑、实物挂了”的反向问题。更关键的是PWM 定时器每 10us 中断一次会打断 DS18B20 的读时隙采样。解决方法是读温度前关掉定时器0中断读完再开sbit DQ P3^7; // DS18B20数据引脚 void DS18B20_Reset(void) { DQ 0; Delay_Us(480); // 480us复位脉冲 DQ 1; Delay_Us(80); // 此处检测存在脉冲简化处理 Delay_Us(400); } void Read_Temperature(void) { unsigned char low, high; ET0 0; // 关闭PWM中断保护单总线时序 DS18B20_Reset(); // 跳过ROM、启动转换的写指令省略 DS18B20_Reset(); low DQ_ReadByte(); // 温度低字节 high DQ_ReadByte(); // 温度高字节 ET0 1; // 恢复PWM输出 // 温度拼接与符号处理 }逻辑说明ET00 期间定时器0停止PWM_OUT 保持最后电平电机在温度采集的几毫秒内会短暂停转但因为温度采集周期通常是 500ms 一次这几毫秒不会引起肉眼可见的转速波动。如果温度读取频率提高需要把采集放到 PWM 的低电平区间做但课程设计里关中断是最可靠的方案。4.2 温度偏差到占空比的线性映射比例映射公式是最终占空比 手动设定占空比 (当前温度 - 设定温度) × Kp。Kp 取 2 时温度每高 1 度占空比增加 2%到 95% 饱和。映射关系可以做成表格方便答辩讲解温度区间修正动作Kp 作用低于设定温度 3 度以上不修正按手动占空比输出避免低温下电机全速转高于设定温度 3 度以内按偏差比例增加占空比线性散热转速平滑上升高于设定温度 10 度以上占空比饱和到 95%防止占空比越界损坏驱动管这个映射本质是 P 控制器没有积分项所以存在稳态误差但对风扇类负载足够。不要在这个题目里强行套完整 PID单片机资源有限且答辩验收只看温度变化时占空比是否跟随比例控制演示效果最直观。4.3 温度读取与 PWM 联动代码unsigned int temperature; // 当前温度单位0.1℃ unsigned char manual_pulse; // 手动设定占空比 unsigned char final_pulse; // 最终输出占空比 #define SET_TEMP 250 // 设定温度25.0℃ #define KP 20 // 比例系数单位0.1℃ void Temperature_Control(void) { int delta; temperature Read_Temperature(); // 读取DS18B20 delta (int)temperature - SET_TEMP; // 温度偏差 if (delta 0) delta 0; // 低温不修正 final_pulse manual_pulse (delta * KP) / 100; if (final_pulse 95) final_pulse 95; // 上限饱和 if (final_pulse 5) final_pulse 5; // 下限保护 pulse final_pulse; // 更新定时器使用的占空比 }逻辑说明SET_TEMP 用 250 表示 25.0℃Read_Temperature 返回的温度也是 0.1℃ 单位这样小数部分不会丢失。delta 的单位是 0.1℃KP 设成 20 表示每 1℃ 偏差修正 2% 占空比。乘法在 51 上不会溢出delta 最多几百乘 20 后仍在 int 范围内。manual_pulse 是按键加减的结果temperature 是反馈量final_pulse 是合成后的实际输出三个变量区分清楚答辩时逻辑链就很顺。4.4 Proteus 仿真接线与温度模型调整仿真接线时DS18B20 的 DQ 接 P3.7VCC 接 5VGND 接地DQ 到 VCC 之间放一个 4.7k 电阻。Proteus 里想要演示温度变化不要在原理图里直接改器件属性运行时双击 DS18B20在属性窗口的 Model Parameters 里调整 Temperature 或使用滑动条仿真会自动刷新。此时观察电机转速温度值调高PWM 占空比上升电机明显加速调回低温占空比回落到手动设定值。这个演示过程是整个答辩的核心证据。5. 物料清单、流程图与示波器验收5.1 一份可以直接按图采购的 BOM 表序号元件规格参数数量备注151单片机STC89C52RC 或 AT89C511Proteus 用 AT89C52 替代2晶振12MHz1机器周期 1us3瓷片电容30pF2晶振负载电容4电解电容10uF/25V1复位电路5电阻10kΩ1复位下拉6电阻4.7kΩ2DS18B20 上拉、备用7排阻10kΩ × 81P0 口上拉8按键6×6mm 轻触3加速、减速、模式9电机驱动ULN2003A1达林顿管阵列10直流电机3-6V 玩具电机1可带减速器11温度传感器DS18B20 TO-921单总线通信12数码管两位共阴1显示温度或占空比13电源5V/1A1单片机与电机分路供电5.2 程序流程图与中断优先级设计全系统只有两个中断源定时器0中断输出 PWM温度采集期间临时关闭定时器0中断。主循环工作流程是初始化各模块读取 DS18B20按键扫描更新 manual_pulse调用温度控制合成 final_pulse刷新数码管循环往复。画流程图时要注意把 PWM 输出画成独立分支不要画进主循环因为主循环里任何一条延时语句都会阻塞十个 PWM 周期波形上会出现明显毛刺。答辩时判断流程图是否合格的标准是看“温度读取放哪一步”。放在主循环头部的是正确画法放进中断服务程序的属于概念错误单总线读写本身要关中断再把读取放回中断等于把系统卡死在嵌套里。流程图里还要画出异常分支DS18B20 复位失败时显示错误代码并重试而不是继续执行读温度否则温度值会保持上一次的残留数据。5.3 用 Proteus 虚拟示波器验证 PWM 调制的最后一步仿真运行后从左侧工具栏选择虚拟仪器 OSCILLOSCOPE把 A 通道探针接到 P1.0地线接到 GND运行后能看到一组频率约 1kHz 的方波。按加速键观察高电平宽度逐步变宽这就是占空比可调的直接证据。再把示波器 A 通道切换为平均值测量按键从低速扫到高速平均值应该是一条平滑上升的斜坡。如果平均值出现台阶先查 pulse 变量的赋值时机按键扫描和温度控制都在改 pulse最终输出前必须经过限幅限幅之后的 pulse 不能再被其他分支污染。把示波器显示比例调到 1ms/格对比加速前后的占空比数值与代码里的 pulse 值完全一致时这个项目就具备实物移植条件了。本文还有配套的精品资源点击获取