蓝桥杯单片机综合练习——工厂灯光控制

一、题目

二、代码

cpp 复制代码
#include <reg52.h>

sfr AUXR = 0x8e;    //定义辅助寄存器

sbit S5 = P3^2;     //定义S5按键引脚
sbit S4 = P3^3;     //定义S4按键引脚

unsigned char led_stat = 0xff;      //定义LED当前状态
unsigned char count = 0;            //定义50ms定时中断累计变量
unsigned char t_h =  0;             //定义运行时间的时变量
unsigned char t_m =  0;             //定义运行时间的分变量
unsigned char t_s =  0;             //定义运行时间的秒变量
unsigned char command = 0;          //定义串口命令字接受变量

//========共阳极数码管的段码表============
unsigned char code SMG_duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
                                   0x82,0xf8,0x80,0x90,0x88,0x80,
                                   0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//=======================================

//============锁存器选择函数==============
/** 
  * @brief 选择要打通的锁存器
  * @param channel------要选择的通道
  * @retval 无
  **/
void SelectHC573(unsigned char channel)
{
    switch(channel)
    {
        case 4:
            P2 = (P2 & 0x1f) | 0x80;
        break;
        case 5:
            P2 = (P2 & 0x1f) | 0xa0;
        break;
        case 6:
            P2 = (P2 & 0x1f) | 0xc0;
        break;
        case 7:
            P2 = (P2 & 0x1f) | 0xe0;
        break;
        case 0:
            P2 = (P2 & 0x1f) | 0x00;
        break;
    }
}
//=======================================

//=================延时函数==============
/** 
  * @brief 延时
  * @param t--延时长度
  * @retval 无
  **/
void Delay(unsigned int t)
{
    while(t--);
}
//=======================================

//===========系统初始化函数==============
/** 
  * @brief 将蜂鸣器、继电器等无关设备关闭
  * @param 无
  * @retval 无
  **/
void InitSystem()
{
    SelectHC573(5);
    P0 = 0x00;
    SelectHC573(4);
    P0 = led_stat;
    SelectHC573(0);
}
//=======================================

//===========设备检测函数================
/** 
  * @brief 逐个检测工厂灯光的工作状态
  * @param 无
  * @retval 无
  **/
void CheckLED()
{
    unsigned int i;
    SelectHC573(4);
    for(i = 0;i < 8; i++)
    {
        led_stat = 0xfe << i;
        P0 = led_stat;
        Delay(60000);
        Delay(60000);
    }
    for(i = 0;i < 8; i++)
    {
        led_stat = ~(0xfe << i);
        P0 = led_stat;
        Delay(60000);
        Delay(60000);
    }
}

/** 
  * @brief 逐个检测数码管的工作状态
  * @param 无
  * @retval 无
  **/
void CheckSMG()
{
    unsigned int i;
    for(i = 0;i < 8; i++)
    { 
        SelectHC573(6);
        P0 = ~(0xfe << i);
        SelectHC573(7);
        P0 = 0x00;
        Delay(60000);
        Delay(60000);
    }
    for(i = 0;i < 8; i++)
    {
        SelectHC573(6);
        P0 = 0xfe << i;
        SelectHC573(7);
        P0 = 0x00;
        Delay(60000);
        Delay(60000);
    }
    SelectHC573(0);
}
//=======================================

//=========数码管显示函数================
/** 
  * @brief 在数码管指定位置上显示指定内容
  * @param pos------数码管选位
           value------数码管显示内容
  * @retval 无
  **/
void DisplaySMG(unsigned char pos,unsigned char value)
{
    P0 = 0xff;
    SelectHC573(6);
    P0 = 0x01 << pos;
    SelectHC573(7);
    P0 = value;
}

/** 
  * @brief 在数码管上显示系统运行时间
  * @param 无
  * @retval 无
  **/
void DisplayTime()
{
    DisplaySMG(7,SMG_duanma[t_s % 10]);     //秒的个位
    Delay(500);
    DisplaySMG(6,SMG_duanma[t_s / 10]);     //秒的十位
    Delay(500);
    DisplaySMG(5,SMG_duanma[16]);           //分隔符
    Delay(500);
    
    DisplaySMG(4,SMG_duanma[t_m % 10]);     //分的个位
    Delay(500);
    DisplaySMG(3,SMG_duanma[t_m / 10]);     //分的十位
    Delay(500);
    DisplaySMG(2,SMG_duanma[16]);           //分隔符
    Delay(500);
    
    DisplaySMG(1,SMG_duanma[t_h % 10]);     //时的个位
    Delay(500);
    DisplaySMG(0,SMG_duanma[t_h / 10]);     //时的十位
    Delay(500);
}
//=======================================

//===========定时器函数==================
/** 
  * @brief 将定时器T0设置为16位模式,计数初值为50ms
  * @param 无
  * @retval 无
  **/
void InitTimer0()
{
    TMOD = 0x21;                    //T0和T1定时器工作模式同时赋值
    TH0 = (65535 - 50000) / 256;
    TL0 = (65535 - 50000) % 256;
    
    ET0 = 1;                        //使能定时器T0
    EA = 1;                         //使能总中断
    TR0 = 1;                        //启动定时器T0
}

/** 
  * @brief 进行系统运行时间的处理
  * @param 无
  * @retval 无
  **/
void Timer0() interrupt 1
{
    TH0 = (65535 - 50000) / 256;
    TL0 = (65535 - 50000) % 256;
    count ++;
    if(count == 20)
    {
        count = 0;
        t_s ++;
    }
    if(t_s == 60)
    {
        t_s = 0;
        t_m ++;
        if(t_m == 60)
        {
            t_m = 0;
            t_h++;
        }
    }
}
//=======================================

//==============串口函数=================
/** 
  * @brief 将串口初始化为模式一,波特率为9600,允许接收
  * @param 无
  * @retval 无
  **/
void InitUart()
{
    TMOD = 0x21;        //T0和T1定时器工作模式同时赋值
    TH1 = 0xfd;         //设置9600波特率的参数
    TL1 = 0xfd;
    TR1 = 1;            //启动定时器T1
    
    SCON = 0x50;        //8为UART模式,允许接收
    AUXR = 0x00;        //辅助寄存器设置
    ES = 1;             //使能串口中断
    EA = 1;             //使能总中断
}

/** 
  * @brief 接收上位机的数据并保存在command变量中
  * @param 无
  * @retval 无
  **/
void Uart() interrupt 4
{
    if(RI == 1)
    {
        command = SBUF;     //将接收到的数据保存到command中
        RI = 0;             //接收完成后,将接收标志位RI清0
    }
}

/** 
  * @brief 串口给上位机发送一个字节
  * @param dat------串口发送的内容
  * @retval 无
  **/
void SendByte(unsigned char dat)
{
    SBUF = dat;         //把dat中的内容发送给上位机
    while(TI == 0);
    TI = 0;             //发送完成后,将发送标志位RI清0
}
//=======================================

//========上位机命令解析执行函数=========
/** 
  * @brief 接收上位机的数据并保存在command变量中
  * @param 无
  * @retval 无
  **/
void ExecuteCommand()
{
    if(command != 0x00)     //接收到上位机命令
    {
        switch(command & 0xf0)      //将命令类型取出来
        {
            case 0xa0:      //远程控制灯光
                SelectHC573(4);
                led_stat = (led_stat | 0x0f) & (~command | 0xf0);
                P0 = led_stat;
                SelectHC573(0);
                command = 0x00;
            break;
            case 0xb0:      //读取现场系统运行时间
                SendByte((t_h / 10 << 4) | (t_h % 10));
                SendByte((t_m / 10 << 4) | (t_m % 10));
                SendByte((t_s / 10 << 4) | (t_s % 10));
                command = 0x00;
            break;
        }
    }
}
//=======================================

//==========按键扫描函数=================
/** 
  * @brief 扫描S4与S5按键并执行现场灯光控制
  * @param 无
  * @retval 无
  **/
void ScanKeys()
{
    if(S4 == 0)
    {
        Delay(500);             //按键消抖
        if(S4 == 0)             //确认按键按下
        {
            while(S4 == 0)      //等待按键松开
            {
                DisplayTime();
            }
            SelectHC573(4);
            led_stat = (led_stat | 0x80) & (~led_stat | 0x7f); 
            P0 = led_stat;      //执行现场灯光控制
            SelectHC573(0);
        }
    }
    if(S5 == 0)
    {
        Delay(500);             //按键消抖
        if(S5 == 0)             //确认按键按下
        {
            while(S5 == 0)      //等待按键松开
            {
                DisplayTime();
            }
            SelectHC573(4);
            led_stat = (led_stat | 0x40) & (~led_stat | 0xbf); 
            P0 = led_stat;      //执行现场灯光控制
            SelectHC573(0);
        }
    }
}
//=======================================

//===============主函数==================
void main()
{
    InitSystem();
    CheckLED();
    CheckSMG();
    InitTimer0();
    InitUart();
    while(1)
    {
        ExecuteCommand();
        DisplayTime();
        ScanKeys();
    }
}
//=======================================
相关推荐
天月风沙2 小时前
PX4 | 无人机关闭磁力计罗盘飞行(yaw estimate error报错解决方法)
单片机·嵌入式硬件·mcu·无人机
计蒙不吃鱼5 小时前
星闪开发之Server-Client 指令交互控制红灯亮灭案例解析(SLE_LED详解)
嵌入式硬件·物联网·iot·星闪·星闪开发
想搞嵌入式的小白5 小时前
STM32 NVIC中断控制器
stm32·单片机·嵌入式硬件·nvic
A-花开堪折6 小时前
Android7 Input(十)View 处理Input事件pipeline
android·嵌入式硬件
深圳市尚想信息技术有限公司6 小时前
【深尚想】OPA855QDSGRQ1运算放大器IC德州仪器TI汽车级高速8GHz增益带宽的全面解析
单片机·嵌入式硬件
陕西艾瑞科惯性技术有限公司7 小时前
让飞行姿态 “可感知”:为什么无人机需要三轴陀螺仪?
嵌入式硬件·机器学习·机器人·无人机·pcb工艺
代码总长两年半7 小时前
STM32----IAP远程升级
stm32·单片机·嵌入式硬件
广药门徒8 小时前
STM32手册上标称的18MHz GPIO翻转速度和你实际测量到的速度之间的差异是预期之内且合理的
单片机·嵌入式硬件
广药门徒8 小时前
在使用一些不用驱动大电流的设备就可以用stm32的自己的上下拉但是本身上下拉不就是给iicspi这些他通信给信号的吗中怎么还跟驱动能力扯上了有什么场景嘛
stm32·单片机·fpga开发
jz_ddk9 小时前
[zynq] Zynq Linux 环境下 AXI BRAM 控制器驱动方法详解(代码示例)
linux·运维·c语言·网络·嵌入式硬件