单元训练02:蜂鸣器与继电器的控制

蓝桥杯

小蜜蜂

cpp 复制代码
#include "STC15F2K60S2.h"
// 定义控制LED
#define Led(x)                 \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0x80; \
        P2 &= 0x1f;            \
    }
// 定义控制蜂鸣器
#define Buzz(x)                \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0xA0; \
        P2 &= 0x1F;            \
    }
// 定义控制继电器
#define Relay(x)               \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0xA0; \
        P2 &= 0x1F;            \
    }

typedef unsigned char u8; // 自定义类型
u8 TimerCounter = 0;      // 时间计数
u8 Bool500msOn = 0;       // 0.5s是否达到
u8 LedInfo = 0xff;        // LED灯状态信息
u8 LedCounter = 0;        // LED计数,切换灯
u8 RelayCounter = 0;      // 继电器计数,打开时间
u8 BuzzCounter = 0;       // 蜂鸣器计数,蜂鸣时间

u8 BoolRelay = 0; // 继电器是否启用
u8 BoolBuzz = 0;  // 蜂鸣器是否启用

u8 LedStatus = 0;   // LED状态机
u8 RelayStatus = 0; // 继电器状态机
u8 BuzzStatus = 0;  // 蜂鸣器状态机

void Timer0_Init(void) // 5毫秒@12.000MHz,STC-ISP产生 
{
    AUXR |= 0x80; // 定时器时钟1T模式
    TMOD &= 0xF0; // 设置定时器模式
    TL0 = 0xA0;   // 设置定时初始值
    TH0 = 0x15;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时
    ET0 = 1;      // 使能定时器0中断
    EA = 1;
}

void LedProc()
{
    switch (LedStatus)
    {
    case 0: // 默认状态为3次闪烁
        LedInfo = ~LedInfo;
        Led(LedInfo);
        if (LedCounter++ == 5) // 计到5时,正好是3次亮灭重复出现
        {
            LedStatus = 1;  // 切换到下一个状态机
            LedCounter = 0; // 计数归0
            LedInfo = 0xff; // 设置下个状态的LED状态
        }
        break;
    case 1:                     // 依次点亮情况
        LedInfo = LedInfo << 1; // 左移
        Led(LedInfo);           // 点亮
        if (++LedCounter == 8)  // 一共8位LED,所以计数8
        {
            LedStatus = 2;  // 切换状态机
            LedCounter = 0; // 计数归0
            BoolRelay = 1;  // 依次点亮LED后,就是操作继电器,所以设定继电器状态启用
        }
        break;
    case 2:             // 等待状态,等待继电器 吸合 再断开后,进行依次熄灭LED的中间过渡
        LedInfo = 0x00; // 因为依次熄灭使用的是取反操作,所以初始状态设为0x00。
        if (!BoolRelay) // 继电器关闭,进入LED下一状态
            LedStatus = 3;
        break;
    case 3:
        LedInfo = ~(0xff << ++LedCounter); // 依次熄灭
        Led(LedInfo);
        if (LedCounter == 8) // LED8位,所以计数8
        {
            LedStatus = 4;  // LED依次熄灭后,需要操作蜂鸣器,所以再加一个状态4
            LedCounter = 0; // 计数归0
            LedInfo = 0xff; // 状态0时进入LED初始情况
            BoolBuzz = 1;   // 蜂鸣器准备启用
        }
        break;
    case 4:
        if (!BoolBuzz) // 蜂鸣器关闭,开始回到最初3次8位LED闪烁情况
            LedStatus = 0;
    }
}

void RelayProc()
{
    switch (RelayStatus)
    {
    case 0: // 默认状态,等待继电器启用
        if (BoolRelay)
            RelayStatus = 1; // 启用后,进入下一状态
        break;
    case 1:
        Relay(0x10);             // 继电器吸合情况
        if (RelayCounter++ == 2) // 1s,此处可调整
            RelayStatus = 2;     // 吸合一会后,要断开,进入状态2,即要断开
        break;
    case 2:
        Relay(0x00);      // 继电器断开
        RelayStatus = 0;  // 继电器状态归 0
        BoolRelay = 0;    // 继电器关闭
        RelayCounter = 0; // 计数归0
        break;
    }
}

void BuzzProc()
{
    switch (BuzzStatus)
    {
    case 0: // 蜂鸣器初始状态,等待启用
        if (BoolBuzz)
            BuzzStatus = 1; // 启用,转到下一状态
        break;
    case 1:
        Buzz(0x40);             // 蜂鸣器响,
        if (BuzzCounter++ == 2) // 1s,响的时长,可调整
            BuzzStatus = 3;     // 进入下一状态
        break;
    case 3:
        Buzz(0x00);      // 蜂鸣器关闭
        BuzzStatus = 0;  // 状态归0,关闭
        BuzzCounter = 0; // 计数归0
        BoolBuzz = 0;    // 蜂鸣器不启用
        break;

    default:
        break;
    }
}
void main()
{
    Led(0xFF);     // 设置LED初始状态
    Timer0_Init(); // 启用定时器
    while (1)
    {
        if (Bool500msOn) // 达到计数间隔,0.5s,可调整
        {
            LedProc();   // 操作LED
            RelayProc(); // 操作继电器
            BuzzProc();  // 操作蜂鸣器
        }

        Bool500msOn = 0; // 重新计数
    }
}

void Timer0_Isr(void) interrupt 1
{
    if (TimerCounter++ == 100) // 0.5s
    {
        TimerCounter = 0;
        Bool500msOn = 1;
    }
}
相关推荐
单片机仿真设计1 小时前
【proteus仿真】基于 STM32 农业大棚巡检小车 (仿真图+程序)
stm32·单片机·嵌入式硬件·proteus·毕设
Hello_Damon_Nikola3 小时前
AiP9M161个人护理产品方案从设计到实现
单片机·嵌入式硬件
智购科技无人售货机工厂4 小时前
2026自动售货机热敏打印模块集成:从串口驱动到小票自动裁切的工程实践~YH
android·stm32·单片机·嵌入式硬件·系统架构
736c4 小时前
STM32-PWR 09
stm32·单片机
亿道电子Emdoor4 小时前
【Arm】如何高效实现2兆字节对齐
arm开发·单片机·mcu
智购科技智能售货柜4 小时前
2026自动售货机峰值交易流量应对方案:从消息削峰到弹性扩容的工程实践~YH
数据库·人工智能·单片机·嵌入式硬件·yolo
zcmodeltech5 小时前
煤化工沙盘模型控制系统设计与实现:多工段协同联动方案
网络·人工智能·stm32·嵌入式硬件·制造·多分类
Jaixln_HRF5 小时前
率能SS6216 单通道1.4A/7.2V直流电机驱动芯片,支持正反转/停止/刹车,用于玩具/智能锁/车载夹
驱动开发·嵌入式硬件·硬件工程
CANI_PLUS5 小时前
AD从立创商城找需要的器件,新建自己的元器件库或者添加到原来的库中
嵌入式硬件
泛凡(Linyongui)5 小时前
第四篇、病毒是怎么黑进人体的?DNA病毒与RNA病毒入侵碳基单片机的逻辑完全不同
单片机·嵌入式硬件·程序人生