Day15:直流电机驱动(PWM)
2025-04-06 本文已影响0人
xqiiitan
15 直流电机驱动(PWM)
- 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转
- 直流电机主要由永磁体(定子)、线圈(转子)和换向器组成
- 除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空心杯电机等
PWM: 调速。转一会 停一会,比如1毫秒。转停的速度非常快,从而控制电机的速度。
【PWM: 脉冲宽度调制】,在具【有惯性的系统中】,可以通过对一系列脉冲的宽度进行调制,
来等效地获取所需要的模拟参量,常用于电机提速、开关电源灯邻域。 可以模拟出正弦波。
PWM重要参数:
Ts = Ton + Toff.
频率= 1/Ts
占空比= Ton/Ts 高电位占比。
精度= 占空比变化步距。
15.1 led呼吸灯效果,PWM实现。
#include <REGX52.H>
sbit LED = P2^0;
void Delay(unsigned int t)
{
while(t--);
}
void main()
{
unsigned char Time,i;
while(1)
{
for(Time=0;Time<100;Time++) //改变亮灭时间,由暗到亮
{
for(i=0;i<20;i++) //计次延时,循环20次。
{
LED=0; //LED亮
Delay(Time); //延时Time,占用主循环。
LED=1; //LED灭
Delay(100-Time); //延时100-Time,PWM确保是固定值。
}
}
for(Time=100;Time>0;Time--) //改变亮灭时间,由亮到暗
{
for(i=0;i<20;i++) //计次延时
{
LED=0; //LED亮
Delay(Time); //延时Time
LED=1; //LED灭
Delay(100-Time); //延时100-Time
}
}
}
}
15.2 驱动直流电机调速度,定时器方式实现。
定时器,定时自增,比较用户设置的值。
计数器<比较值,输出0;
计数器≥比较值,输出1;
最终输出PWM 方波波形,重复输出方波信号。
//Delay.h Delay.c 延时
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
//---------------------
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//Key.h 按键
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
//---------------------
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
// Timer0.hc 定时器
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0_Init(void);
#endif
#include <REGX52.H>
/**
* @brief 定时器0初始化,100us@12.000MHz
* @param 无
* @retval 无
*/
void Timer0_Init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x9C; //设置定时初值 100us@12.000MHz,100微秒.
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
/*定时器中断函数模板,PWM写到定时器里面实现
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
*/
//Nixie.c
//数码管段码表 [0-9]
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
/**
* @brief 数码管显示
* @param Location 要显示的位置,范围:1~8
* @param Number 要显示的数字,范围:段码表索引范围
* @retval 无
*/
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1); //显示一段时间
P0=0x00; //段码清0,消影
}
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Timer0.h"
sbit Motor = P1^0; //电机端口
unsigned char Counter,Compare; //计数值0-100和比较值,用于输出PWM;Compare用于控制速度。
unsigned char KeyNum,Speed; //按键序号; 电机要转速度
void main()
{
Timer0_Init();
while(1)
{
KeyNum = Key(); //主循环扫描按键,显示数码管
if(KeyNum==1)
{
Speed++; // 速度0-3循环。
Speed%=4;
if(Speed==0){Compare=0;} //设置比较值,改变PWM占空比,实现电机调速
if(Speed==1){Compare=50;}
if(Speed==2){Compare=75;}
if(Speed==3){Compare=100;}
}
Nixie(1, Speed); //第1个位置,显示速度
}
}
// PWM实现。100us进来一次。
void Timer0_Routine() interrupt 1
{
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
Counter++;
Counter%=100; //计数值变化范围限制在0~99
if(Counter<Compare) //计数值小于比较值,实现电机调速。
{
Motor=1; //输出1
}
else //计数值大于比较值
{
Motor=0; //输出0
}
}