蓝桥杯国信长天单片机实战—呼吸灯设计

利用PWM实现呼吸灯

核心源码

#include "reg52.h"
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long

sbit PWMOUT = P0^0;

u8 HighRH = 0;
u8 HighRL = 0;
u8 LowRH  = 0;
u8 LowRL  = 0;

void ConfigPWM(u16 fr, u8 dc);//注意一个频率一个占空比,频率是u16
void ClosePWM();

void CloseFucker();

void main()
{
    u32 i;
    CloseFucker();
    P2 = (P2 & 0x1F) | 0x80;
    P0 = 0xFF;//务必先关闭,然后才能选通对应的!
    EA = 1;


    while (1)//注意占空比指的是高电平的持续时间,CT107D小灯是低电平点亮。
    {
        ConfigPWM(100, 10);    //频率100Hz,占空比10%
        for (i=0; i<100000; i++);
        ClosePWM();
        ConfigPWM(100, 40);    //频率100Hz,占空比40%
        for (i=0; i<100000; i++);
        ClosePWM();
        ConfigPWM(100, 90);    //频率100Hz,占空比90%
        for (i=0; i<100000; i++);
        ClosePWM();            //关闭PWM,相当于占空比100%
        for (i=0; i<100000; i++);
    }
}

void CloseFucker()
{
    P2 = (P2 & 0x1F) | 0xA0; //关闭蜂鸣器和继电器
    P0 = P0 & 0xAF;
    P2 = 0x00;
}


void ConfigPWM(u16 fr, u8 dc) //这一段配置非常有意思
{
    u32 tmp;//用来存临时总值
    u16 high, low; //用来存高电平低电平的总值

    tmp = (11059200/12)/fr;//算出对应频率的总值
    high = (tmp*dc)/100;//算出高电平总值
    low = tmp - high;//算出低电平总值
    high = 65536 - high;//对应该的计数开始值
    low = 65536 - low;
    HighRH = (u8)(high >> 8);//它们四个是个全局变量,在中断给P00口赋值。
    HighRL = (u8)high;
    LowRH = (u8)(low >> 8);
    LowRL = (u8)low;

//AUXR &= 0x7F;//这里我没加AUXR寄存器的相关设置,15上电默认是12T
    TMOD &= 0xF0;
    TMOD |= 0x01;
    TH0 = HighRH;
    TL0 = HighRL;
    ET0 = 1;
    TR0 = 1;
    PWMOUT = 1;

}

void ClosePWM()
{
    TR0 = 0;
    ET0 = 0;

    PWMOUT = 1;
}

void InterruptTimer() interrupt 1
{
    if(PWMOUT == 1)
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;//注意,赋完值要记得把引脚的电平翻转啊!!!
    }
    else
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}