PWM信号控制呼吸流水灯注释-IO模式(改自于小蜜蜂老师蓝桥杯代码)

【代码介绍】

在观看小蜜蜂老师的进阶强化PWM控制呼吸灯部分代码时,由于代码缺少注释,所以在第一次理解时比较吃力,没理解代码块之间的关联性以及各变量作用。所以这里对代码给出自己的理解注释。

注:本代码基于小蜜蜂老师进阶强化07改编而来,但是不同的是使用的是IO模式而并非是MM模式。

代码部分:

#include <REG52.H>

sbit S4 = P3 ^ 3;
sbit S7 = P3 ^ 0;

unsigned char code Array[18] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
                                0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f};

unsigned char Count;     //定时器计数
unsigned char Flag;      // S4按键模式切换
unsigned char Pause;     //用于在按键长按停止灯光以及数码管
unsigned char direction; // LED灯闪烁方向
unsigned char Position;  // LED灯亮的位置
unsigned char PWM;       //用于记录占空比,同时控制亮度
unsigned char Times;     //用于计次(在LED_Control函数)中,与PWM变量结合使用

void Delay(unsigned int x)
{
    while (x--)
        ;
}

void HC573(unsigned char channel)
{
    switch (channel)
    {
    case 4:
        P2 = (0x1f & P2) | 0x80;
        break;
    case 5:
        P2 = (0x1f & P2) | 0xa0;
        break;
    case 6:
        P2 = (0x1f & P2) | 0xc0;
        break;
    case 7:
        P2 = (0x1f & P2) | 0xe0;
        break;
    case 0:
        P2 = (0x1f & P2);
        break;
    }
}

void Nixie(unsigned char column, unsigned char row)
{
    P0 = 0xff;
    HC573(7);
    HC573(0);
    P0 = 0x01 << column;
    HC573(6);
    HC573(0);
    P0 = row;
    HC573(7);
    HC573(0);
}

void Display(unsigned char column, unsigned char row)
{
    Nixie(0, Array[column]);
    Delay(500);

    Delay(500);
    Nixie(6, Array[row / 10]);
    Delay(500);
    Nixie(7, Array[row % 10]);
    Delay(500);

    Nixie(0, 0xff);
    Delay(500);
    Nixie(6, 0xff);
    Delay(500);
    Nixie(7, 0xff);
    Delay(500);
}

void System_Init()
{
    HC573(5);
    P0 = 0x00;
    HC573(4);
    P0 = 0xFF;
    HC573(0);
}

void Timer_Init() //定时器
{
    TMOD = 0x01;
    TH0 = (65535 - 1000) / 256;
    TL0 = (65535 - 1000) % 256;
    TF0 = 0;
    TR0 = 1;
    EA = 1;
    ET0 = 1;
}

void San_Key()
{
    if (S4 == 0)
    {
        Delay(100);
        if (S4 == 0)
        {
            while (S4 == 0)
            {
                Pause = 1; //按键S4长按,暂停呼吸灯,显示数码管,标志位置1;
            }
            Pause = 0;     //松开S4,呼吸灯继续运行
            Flag++;        //模式切换标志位
            if (Flag == 3) //模式只有正向闪烁和逆向闪烁两种模式
            {
                Flag = 1;
            }
        }
    }
    if (S7 == 0)
    {
        Delay(100);
        if (S7 == 0)
        {
            while (S7 == 0)
            {
                Pause = 1;                       // S7按下,同样暂停呼吸灯
                Display(Position + 1, PWM * 10); //在数码管上显示当前亮灯以及占空比
            }
            Pause = 0; //松开继续运行
        }
    }
}

void LED_Control() // LED呼吸灯
{
    //这里的Times和定时器中的PWM变量相互结合。
    /*定时器每10ms(Count》10),Times加1,而Times加到5之后,置0,组合一起为50ms。
    也即是每50ms使PWM占空比+1,当占空比为10时,总共为500ms也即是0.5s,实现缓慢亮0.5s*/
    if (Times == 5)
    {
        Times = 0;
        if (direction == 0)
        {
            PWM += 1;      //占空比,50ms+1,总共时间为500ms,所以在数码管显示阶段会将占空比*10。
            if (PWM == 11) // PWM达到10之后,完成0.5s亮,置0,进行0.5s灭操作
            {
                PWM = 10;
                direction = 1;
            }
        }
        else if (direction == 1)
        {
            PWM -= 1;
            if (PWM == 255) // PWM类型为unsigned char(范围0~256),等价于(PWM<0)
            {
                PWM = 0;
                direction = 0;
                if (Flag == 1) //正向闪烁模式
                {
                    Position++; //亮灯位置加1,使下一位灯开始亮
                    if (Position == 8)
                    {
                        Position = 0;
                    }
                }
                else if (Flag == 2) //逆向闪烁模式
                {
                    Position--;
                    if (Position == 255) //等价于(Position<0)
                    {
                        Position = 7;
                    }
                }
            }
        }
    }
}

void main()
{
    System_Init();
    Timer_Init();
    while (1)
    {
        San_Key();
        LED_Control();
    }
}

void Timer() interrupt 1
{
    TH0 = (65535 - 1000) / 256;
    TL0 = (65535 - 1000) % 256;
    if (Flag == 0) //初始化L4,L5亮
    {
        HC573(4);
        P0 = 0xe7;
        return;
    }
    Count++;
    /*这里PWM为一个标识量,Count小于PWM时亮,大于PWM小于10时灭,
    10ms使Times++,5次后PWM变化(即亮度进行变化)*/
    if (Count <= PWM)
    {
        P0 = ~(0x01 << Position);
        HC573(4);
        HC573(0);
    }
    else if (Count <= 10)
    {
        P0 = 0xff;
        HC573(4);
        HC573(0);
    }
    else
    {
        //这一步亮灯操作不加好像也没影响
        P0 = ~(0x01 << Position);
        HC573(4);
        HC573(0);
        Count = 0;
        if (Pause == 0)
        {
            Times++;
        }
    }
}

最后运行时,在长按按键显示数码管时,还是会导致数码管轻微闪烁,没有完全做到消影。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值