五一单片机之呼吸灯与直流电机调速

文章介绍了如何使用PWM(脉冲宽度调制)技术来调节LED灯的亮度和直流电机的速度。通过在单片机中控制灯亮灭的时间比例,即占空比,实现了亮度的模拟调整。文中还提供了具体的C语言代码示例,展示了如何用定时器和中断功能来实现PWM控制,以及如何通过按键改变电机的转速。
摘要由CSDN通过智能技术生成

首先,我们要解决一个问题,就是我们如何去调节LED灯的亮度?第一时间想到的肯定是调电压,只要电压低,亮度不久下来了吗?确实是这样的,但是在单片机中调节电压不现实,所以我们采用让灯亮一下,灭一会,我们通过控制供电的时间,来达到控制LED灯的亮度。其实PWM也是这样类似的思想,那我们从控制灯的亮度开始,来慢慢理解PWM的工作原理吧!

呼吸灯的实现

#include <REGX52.H>

sbit LED=P2^0;

void LED_Delay(unsigned int t)//延时函数
{
    while(t--);
}

unsigned char Time,i;
void main()
{
    while(1)
    {
        for(Time=0;Time<100;Time++)//改变亮灭时间
        {
            for(i=0;i<20;i++)//计次延时,使得效果更加明显
            {
                LED=0;//LED亮
                LED_Delay(Time);
                LED=1;//LED不亮
                LED_Delay(100-Time);//这一段代码是越来越亮
            }
        }
        for(Time=0;Time<100;Time++)//改变亮灭时间
        {
            for(i=0;i<20;i++)//计次延时,使得效果更加明显
            {
                LED=1;//LED不亮
                LED_Delay(Time);
                LED=0;//LED亮
                LED_Delay(100-Time);//这一段代码是越来越暗
            }
        }
//这样一亮一暗就形象的叫做呼吸灯   

1.直流电机的介绍

2.驱动电路

后面那个相当三极管,起到放大电路的作用,下面的二极管起到保护电路的作用,因为电机可能感应出来比较大电压,从而烧坏电路

如果Q1,Q3导通的话,Q2,Q4不导通,通的就是正向电流

如果Q2,Q4导通的话,Q1,Q3不导通,通的就是反向电流

就是通过导通Q1、Q4形成正向电流或者Q2、Q3形成反向电流,但就是需要确保反向电流不会损坏电路

3.PWN的介绍

4.产生PWN的方法

5.代码实现

1.LED控制速度
main.c
#include <REGX52.H>
#include "Key.h"
#include "Timer0.h"
#include "Delay.h"
#include "Nixie.h"

sbit LED=P2^0;//对LED进行调速

unsigned char Counter,Compare;    //计数值和比较值,用于输出PWM
unsigned char KeyNum,Speed;

void main()
{
    Timer0_Init();
    while(1)
    {
        KeyNum=Key();
        if(KeyNum==1)
        {
            Speed++;
            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);
    }
}

void Timer0_Routine() interrupt 1
{
    TL0 = 0x9C;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    Counter++;
    Counter%=100;    //计数值变化范围限制在0~99
    if(Counter<Compare)    //计数值小于比较值
    {
        LED=0;        //输出0,亮
    }
    else                //计数值大于比较值
    {
        LED=1;        //输出1,不亮
    }
}
Key.h&c
#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;
}

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

Nixie.h&c
#include <REGX52.H>
#include "Delay.h"

//数码管段码表
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,消影
}
#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie(unsigned char Location,Number);

#endif
delay.h&c
void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}
#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif
Timer0.h&c
#include <REGX52.H>

/**
  * @brief  定时器0初始化,100us@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0_Init(void)
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x9C;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;
    EA=1;
    PT0=0;
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
    static unsigned int T0Count;
    TL0 = 0x9C;        //设置定时初值
    TH0 = 0xFF;        //设置定时初值
    T0Count++;
    if(T0Count>=1000)
    {
        T0Count=0;
        
    }
}
*/
#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0_Init(void);

#endif

2直流电机调速(通过小风扇使得效果更加明显)

和led相比代码上只有小小的改变,就是把那个LED换成我们的电机了而已

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值