工厂灯光控制系统案例解析

  • 题目
  • 流程图
  • 关键点复盘
  • 参考代码(IO模式)

题目

流程图

关键点复盘

  • 设备检测——移位
    L1~L8在板子上是从左至右,但是在对P0口赋值时是16进制从高位(L8)—>低位(L0)
    根据原理图,LED赋值0亮1灭
    为了方便赋值,可以把板子转一下,让LED排序与赋值顺序相同
    左移<< 右移>> 控制移位补0,使LED依次点亮、依次熄灭
    unsigned char i 作为下文表格中的循环变量

赋值 L8 L7 L6 L5 L4 L3 L2 L1 备注
0xff 1 1 1 1 1 1 1 1 全灭
0xff << i for(i = 1;i <= 8;i++)
左移补0
~ (0xff) 0 0 0 0 0 0 0 0 全亮
~ (0xff) << i for(i = 1;i <= 8;i++)
左移补1
  • 运行时间的逻辑处理——if语句

    • if语句嵌套:秒——>分——>时
    • 定义unsigned chat count = 0; 将50ms作为计数初值,20次为1s
    • 判断 秒、分 是否到60,而不是59
  • 按键控制LED时不影响数码管运行——按键消抖 检测松手(现场保护)

    if(S5 == 0)                       //发现按键S5信号
    {SMG_Display();             //刷新数码管 作为 去抖动处理if(S5 == 0)                   //确认按键S5信号{while(S5 == 0)         //等待按键S5松开{SMG_Display();       //刷新数码管使其不受按键影响}XXXXXXXXXXX其他操作XXXXXXXXXXXX;}
    }
    
  • 串口远程控制——switch-case-break语句
    根据同信规约:
    高位——命令类型 A 或 B
    低位——执行函数 LED显示 或 读取时间

       if(command != 0x00)  //接收到一个上位机命令{switch(command & 0xf0)  //将命令类型(高4位)取出{case 0xa0:XXXXXXXXX其他操作XXXXXXXXXX;break;command = 0x00;     //command清零,防止重复执行case 0xb0:XXXXXXXXX其他操作XXXXXXXXXX;break;command = 0x00; }}
  • LED控制语句解析——与、或
  • 与或关系
    0 | any = any 用作取数
    1 | any = 1 用作置1
    0 & any = 0 用作置0
    1 & any = any 用作取数
  • 为了使“本地控制”(高位)与“远程控制”(低位)互不干扰,引入状态变量stat_led = 0xff
  • 本地控制
    - S5控制L7(判断S5按下后)
    Select_HC573(4);
    stat_led = (stat_led | 0x40) & (~stat_led | 0xbf);
    P0 = stat_led;
  • 远程控制(判断为case 0xa0以后)
    Select_HC573(4);
    stat_led = (stat_led | 0x0f) & (~command | 0xf0);
    P0 = stat_led;
  • 读取时间——发送数据HEX16进制的BCD码格式(0xMM)
    (hour / 10) << 4 | (hour % 10)
    (min / 10) << 4 | (min % 10)
    (sec / 10) << 4 | (sec % 10)
    原数取整放高位(左移4位),原数取余放低位
  • 注释规范性

    • 标明定义变量

      • 定义辅助寄存器(使用串口时)
      • 定义独立按键管脚(使用独立按键时)
      • 定义状态机(LED状态变量)
      • 定义数码管段码表(有无小数点)
    • 表明定义函数
      /* ==================== XXX函数 =======================
      功能:XXX
      参数:XXX
      返回:XXX
      设计:XXX(20XX年XX月XX日)
      ======================================================= */

参考代码(IO模式)

J13接2~3
J5接2~3

#include "reg52.h"sfr AUXR = 0x8e;        //定义辅助寄存器sbit S5 = P3^2;       //定义按键S5引脚
sbit S4 = P3^3;            //定义按键S4引脚unsigned char count = 0;     //定义50ms定时中断累计变量
unsigned char sec = 0;         //定义运行时间的“秒”变量
unsigned char min = 0;         //定义运行时间的“分”变量
unsigned char hour = 0;            //定义运行时间的“时”变量unsigned char command = 0x00;   //定义串口命令字接受变量unsigned char stat_led = 0xff;  //定义LED灯当前开关状态//-----共阳数码管的段码编码表(无小数点)-----
code unsigned char SMG_NoDot[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};/*====================锁存器选择函数=======================
功能:选择要打通的锁存器
参数:channel 输出通道
返回:空
设计:饥饿的半导体(2023年1月30日)
=======================================================*/
void Select_HC573(unsigned char channel)
{switch(channel){case 4: P2 = P2 & 0x1f | 0x80; break;     //Y4输出0,选择LED控制case 5: P2 = P2 & 0x1f | 0xa0; break;        //Y5输出0,选择蜂鸣器和继电器控制case 6: P2 = P2 & 0x1f | 0xc0; break;        //Y6输出0,选择数码管位选case 7: P2 = P2 & 0x1f | 0xe0; break;        //Y7输出0,选择数码管段码case 0: P2 = P2 & 0x1f | 0x00; break;        //所有锁存器不选择}
}
/*=================数码管专用延时函数==================
功能:数码管动态显示专用延时函数
参数:t 延时长度
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void SMG_Delay(unsigned char t)
{while(t--);
}
/*===============单个数码管显示函数===================
功能:在指定的数码管位置上显示指定的内容
参数:pos——位选,即要点亮的数码管的显示位置dat——段选,即要点亮的数码管的显示内容
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void SMG_Bit(unsigned char pos,unsigned char dat)
{Select_HC573(7);  //消影P0 = 0xff;Select_HC573(6);  //位选(低位—>高位 即 数码管左—>数码管右)P0 = 0x01 << pos;Select_HC573(7);  //段选(内容由“定义的数码管段码数组内容”决定)P0 = dat;
}
/*================全部数码管显示函数===================
功能:控制所有数码管显示相同内容,放在数码管显示函数后用于消影
参数: dat 段选,数码管显示内容
返回:空
设计:饥饿的半导体(2023年1月30日)
====================================================*/
void SMG_All(unsigned char dat)
{Select_HC573(6);  //位选全部P0 = 0xff;Select_HC573(7);  //段选P0 = dat;
}
/*=================普通延时函数=======================
功能:逐个检测LED与数码管的工作状态
参数:t 延时长度
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Delay(unsigned int t)
{while(t--);while(t--);
}
/*=================设备检测函数=====================
功能:逐个检测LED与数码管的工作状态
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Device_Detect()
{unsigned char i;               //循环变量Select_HC573(4);      for(i = 1;i <= 8;i++){P0 = 0xff << i;             //逐个点亮LEDDelay(60000);}for(i = 1;i <= 8;i++){P0 = ~(0xff << i);           //逐个熄灭LEDDelay(60000);}Select_HC573(0);             //关闭所有锁存器Select_HC573(7);               //数码管a~dp所有段点亮P0 = 0x00;for(i = 0;i <= 7;i++){Select_HC573(6);  P0 = ~(0xfe << i);           //逐个点亮数码管Delay(60000);}for(i = 0;i <= 7;i++){Select_HC573(6);  P0 = (0xfe << i);          //逐个熄灭数码管Delay(60000);}Select_HC573(0);             //关闭所有锁存器
}
/*=================定时器T0初始化函数===================
功能:将定时器T0设置为16位自动重装模式(模式00),计数初值为50ms
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Init_Time0()
{TMOD = 0x20;      //注意!!!T0与T1的工作模式必须一起赋值TH0 = (65535 - 50000) / 256;       //计数初值为50msTL0 = (65535 - 50000) % 256;ET0 = 1;       //使能定时器T0EA = 1;           //使能总中断TR0 = 1;        //启动定时器T0
}
/*=================定时器T0中断服务函数=================
功能:进行系统运行时间的逻辑处理
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Service_Time0() interrupt 1
{count++;if(count == 20){count = 0;sec++;if(sec == 60){sec = 0;min++;if(min == 60){min = 0;hour++;{if(hour == 99)hour = 0;}}}}
}
/*=================串口初始化函数===================
功能:将串口初始化为波特率发生器(模式01),波特率为9600,允许接收
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Init_Uart()
{TMOD = 0x20;      //注意!!!T0与T1的工作模式必须一起赋值TH1 = 0xfd;            //设置9600波特率的参数TH1 = 0xfd;SCON = 0x50;     //8位UART模式,允许接收AUXR = 0x00;     //辅助寄存器设置ES = 1;               //使能串口中断EA = 1;                //使能总中断TR1 = 1;            //启动定时器T1}
/*=================串口中断服务函数===================
功能:接收上位机的数据并保持在command变量中
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Service_Uart() interrupt 4
{if(RI == 1){command = SBUF;         //将接收到的数据保存在command变量中RI = 0;                  //将接收完成标志RI清0}
}
/*=================串口发送单字节函数===================
功能:串口向上位机发送一个字节
参数:dat 要发送的字节
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Sent_Byte(unsigned char dat)
{SBUF = dat;while(TI == 0);TI = 0;
}
/*=================系统运行时间显示函数=================
功能:在数码管上显示系统运行的时间
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void SMG_Display()
{SMG_Bit(0,SMG_NoDot[hour / 10]);       //时十位SMG_Delay(500);SMG_Bit(1,SMG_NoDot[hour % 10]);        //时个位SMG_Delay(500);SMG_Bit(2,0xbf);                //分隔符SMG_Delay(500);SMG_Bit(3,SMG_NoDot[min / 10]);         //分十位SMG_Delay(500);SMG_Bit(4,SMG_NoDot[min % 10]);         //分个位SMG_Delay(500);SMG_Bit(5,0xbf);                //分隔符SMG_Delay(500);SMG_Bit(6,SMG_NoDot[sec / 10]);         //秒十位SMG_Delay(500);SMG_Bit(7,SMG_NoDot[sec % 10]);         //分个位SMG_Delay(500);SMG_All(0xff);
}
/*================独立按键控制本地灯光函数===============
功能:扫描S5和S4按键并执行本地灯光控制
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Key_LED()
{if(S5 == 0)                      //发现按键S5信号{SMG_Display();               //去抖动处理if(S5 == 0)                    //确认按键S5信号{while(S5 == 0)         //等待按键S5松开{SMG_Display();}Select_HC573(4);stat_led = (stat_led | 0x40) & (~stat_led | 0xbf); P0 = stat_led;           //执行现场灯光控制Select_HC573(0);}     }if(S4 == 0)                      //发现按键S4信号{SMG_Display();               //去抖动处理if(S4 == 0)                    //确认按键S4信号{while(S4 == 0)         //等待按键S4松开{SMG_Display();}Select_HC573(4);stat_led = (stat_led | 0x80) & (~stat_led | 0x7f); P0 = stat_led;           //执行现场灯光控制Select_HC573(0);}     }
}
/*==================串口远程控制LED函数=====================
功能:上位机命令解析与执行,接收上位机数据并保存在command变量中
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=========================================================*/
void Execute_Command()
{if(command != 0x00)                   //接收到一个上位机命令{switch(command & 0xf0)         //将命令类型(高4位)取出来{case 0xa0:                  //远程灯光控制命令Select_HC573(4);stat_led = (stat_led | 0x0f) & (~command | 0xf0);P0 = stat_led;Select_HC573(0);command = 0x00;         break;case 0xb0:                    //读取本地系统运行时间命令Sent_Byte((hour / 10) << 4 | (hour % 10));Sent_Byte((min / 10) << 4 | (min % 10));Sent_Byte((sec / 10) << 4 | (sec % 10));command = 0x00;break;}}
}
/*==================系统初始化函数=====================
功能:将蜂鸣器与继电器灯无关设备关闭
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void Init_System()
{Select_HC573(5);P0 = 0x00;Select_HC573(4);P0 = 0xff;Select_HC573(0);
}
/*=====================主函数==========================
功能:工厂灯光控制系统的主函数
参数:无
返回:空
设计:饥饿的半导体(2023年1月30日)
=====================================================*/
void main()
{Init_System();  Device_Detect();Init_Time0();Init_Uart();while(1){Execute_Command();SMG_Display();Key_LED();}
}

【蓝桥杯单片机】工厂灯光控制系统案例解析(小蜜蜂老师基础综合实训)相关推荐

  1. 蓝桥杯单片机第七届省赛-模拟风扇控制系统

    九层妖塔 起于垒土 ● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改 蓝桥杯单片机第七届省赛-模拟风扇控制系统 Notes1:按键按下后在某些情况下给一定的缓冲时间 Notes2 ...

  2. 【蓝桥杯单片机(24)】历届单片机客观题及答案解析

    目录 考前冲刺,专栏完结篇 ## 推荐链接: 推荐视频–小蜜蜂老师讲解 赛点资源包下载,提取码:brno 三极管基本知识总结 运算放大电路的基础 第十三届蓝桥杯单片机官方直播课录屏 目录 一些刷题后的 ...

  3. 十三届蓝桥杯单片机组省赛真题程序解析

    第一次参加蓝桥杯,线上比赛,记录一下 比赛刚开始了十分钟才做上客观题,做上了之后才发现看一次题警告一次,当时就蚌埠住了,随便做了做就交了,手册也没怎么查(查一下直接给了3次黄牌,就没敢查了)其实老师1 ...

  4. 蓝桥杯单片机 | 特训案例【进阶06】基于PCF8591的DAC模拟电压输出

    [1]题目要求 新建工程,以I/O模式编写代码,在CT107D单片机综合训练平台上,实现以下功能: 1.将IIC总线的底层驱动代码文件正确移植到工程中. 2.将J5配置BTN模式,把S4设置为独立按键 ...

  5. 蓝桥杯单片机 | 特训案例【进阶03】24C02的基本读写操作

    [1]题目要求 新建工程,以I/O模式编写代码,在CT107D单片机综合训练平台上,实现以下功能: 1.将IIC总线的底层驱动代码文件正确移植到工程中. 2.系统上电后,从24C04存储器的0x01. ...

  6. 蓝桥杯单片机比赛学习:8、PWM的基本原理之呼吸灯

    经过7节的学习,我们已经掌握了基本的硬件的使用规则,从本节开始我们开始学习一些模块的使用PWM.PCF8591.AT24C02.DS18B20.DS1302.555频率测量.光敏电阻测量.超声波测距等 ...

  7. 蓝桥杯单片机比赛学习:6、中断系统之定时器中断的基本原理

    上节我们讲了中断的外部中断,基本的了解了一下中断,这一节我们继续来学习中断系统的定时器中断基本原理,本节很重要无论是在比赛中还是在单片机.嵌入式等的学习上都有着很重要的地位.如对本作者有兴趣可以去我主 ...

  8. 【第十三届蓝桥杯单片机省赛模拟冲刺01】

    第十三届蓝桥杯单片机省赛模拟冲刺 赛前一两周一定要多练习,把之前写过的程序在好好看看,把每个模块的代码都多敲几遍,把常考的每个模块部分都吃透,如果理解不了的趁时间还比较充足该背的背牢.同时在准备编程题 ...

  9. 【蓝桥杯单片机进阶强化-04】PCF8591与24C02综合应用-智能照明自动控制器

    [1]题目要求 在蓝桥杯大赛"单片机设计与开发"的在CT107D综合训练平台上,利用竞赛提供的IIC底层驱动代码,设计程序,实现以下的功能: 1- 系统上电后,通过采样PCF859 ...

最新文章

  1. 如何选择合适的损失函数,请看......
  2. 山东省能源产业项目动态及未来投资决策建议报告2021版
  3. php 不存在给默认值,当属性不存在时,创建一个属性并给它一个默认值
  4. WPF 用装饰器制作抽屉效果
  5. 【ArcGIS风暴】ArcGIS10.6图斑椭球面积计算原理与方法
  6. 和大家谈谈数学模型之美
  7. DTFT、DFT、FFT
  8. 牛客小白月赛4 J 强迫症 思维
  9. 挑战程序设计竞赛——抽签Ⅱ
  10. SMB v1远程代码执行漏洞(CVE-2020-1301)复现
  11. 个人项目总结 (By Jun Guo)
  12. 【IT观察】作为一个DBA,如何选择数据库
  13. [Hox库状态管理思考 二] 类实现组件的数据订阅
  14. 小学一年级计算机社团计划,小学科技兴趣小组活动计划
  15. 海奥华预言--第十一章 谁是基督?
  16. HarmonyOS应用开发实战 | 开发运动手表小游戏
  17. Qt5把图片如何导出为pdf再到剪切板
  18. dbd/oracle,linux centos环境下,perl使用DBD::Oracle遇到报错Can't locate DBDOracle.pm in @INC 的解决办法...
  19. ThreadX学习(4)——内存管理
  20. 【goldengate】官方文档笔记三 Oracle GoldenGate 实时报表

热门文章

  1. MAC 磁盘清理工具 ncdu
  2. java判断字符串是中文乱码_java 检测字符串中文乱码
  3. 计算机比赛小蓝书,AP微积分权威教材:小蓝书来帮你
  4. 过分依赖计算机的危害,惊人研究:过度依赖电脑会使记忆力减退
  5. Android Nginx + RTMP流媒体服务器搭建
  6. 网络功能虚拟化NFV
  7. RocketMQ(三)——HelloWorld
  8. 【商业终端仿真解决方案】上海道宁为您带来Georgia介绍、试用、教程
  9. 考研复试——软件工程笔记归纳+思维导图
  10. 理解java代理模式