在嵌入式系统开发中,PWM(脉冲宽度调制)技术是控制电机速度、LED亮度等设备的常用方法。而51单片机作为经典的入门级微控制器,其PWM功能的实现与调节是每个电子爱好者必须掌握的技能。本文将带你从零开始,通过按键实时调节PWM占空比,实现对电机转速的精确控制。
PWM(Pulse Width Modulation)即脉冲宽度调制,通过调节高电平在一个周期内所占的时间比例(占空比)来控制输出功率。占空比越大,电机转速越快;反之则越慢。
所需硬件组件:
提示:选择电机时需注意其工作电压和电流是否与驱动模块匹配,避免烧毁元件。
硬件连接示意图:
code复制单片机P2.0 → L298N输入A
按键1(P3.4) → 增加占空比
按键2(P3.5) → 减少占空比
L298N输出 → 直流电机
51单片机本身没有硬件PWM模块,但可以通过定时器中断模拟实现。我们使用定时器0工作在模式1(16位定时器模式),通过中断服务程序控制IO口电平变化。
关键参数计算:
c复制void timer0_init() {
TMOD = 0x01; // 定时器0模式1
TH0 = (65536-10)/256;
TL0 = (65536-10)%256;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
}
按键处理需要考虑防抖和响应速度,既要避免误触发,又不能影响PWM波形的稳定性。我们采用软件延时去抖结合状态检测的方法。
按键处理流程:
c复制void Motor_add() { // 增加占空比
if(key_add == 0) {
delayxms(2);
if(key_add == 0) {
count += 0.5; // 步进0.5%
if(count >= 32) count = 32; // 上限32%
}
while(!key_add); // 等待按键释放
}
}
void Motor_dec() { // 减少占空比
if(key_dec == 0) {
delayxms(2);
if(key_dec == 0) {
count -= 0.5; // 步进0.5%
if(count <= 25) count = 25; // 下限25%
}
while(!key_dec); // 等待按键释放
}
}
下面给出完整的可运行代码,并标注关键部分的说明:
c复制#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar time; // 中断计数器
double count = 26; // 初始占空比26%
sbit PWM = P2^0; // PWM输出引脚
sbit key_add = P3^4; // 增加占空比按键
sbit key_dec = P3^5; // 减少占空比按键
void delayxms(uint z) {
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void timer0_init() {
TMOD = 0x01;
TH0 = (65536-10)/256;
TL0 = (65536-10)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void timer0_int() interrupt 1 {
TH0 = (65536-10)/256; // 重装初值
TL0 = (65536-10)%256;
time++;
if(time < count) PWM = 1; // 高电平阶段
else PWM = 0; // 低电平阶段
if(time >= 100) time = 0; // 周期复位
}
void main() {
timer0_init();
while(1) {
Motor_add();
Motor_dec();
}
}
代码优化方向:
在实际项目中,可能会遇到各种问题。以下是几个典型问题及其解决方法:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 电机不转动 | PWM输出引脚配置错误 | 检查P2.0连接是否正确 |
| 按键无反应 | 上拉电阻未接或按键引脚错误 | 确认P3.4/P3.5连接正确,按键有10k上拉 |
| 电机转动不稳定 | PWM频率不合适 | 调整定时器初值改变频率 |
| 占空比调节不线性 | 按键处理延时过长 | 减少delayxms(2)中的延时时间 |
示波器调试技巧:
注意:调试时建议先断开电机,用LED或示波器观察PWM输出,确认正常后再连接电机。