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
    }
}

上一篇 下一篇

猜你喜欢

热点阅读