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

news2024/11/19 9:33:09

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

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

题目

在这里插入图片描述

在这里插入图片描述

流程图

在这里插入图片描述

关键点复盘

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

赋值L8L7L6L5L4L3L2L1备注
0xff11111111全灭
0xff << ifor(i = 1;i <= 8;i++)
左移补0
~ (0xff)00000000全亮
~ (0xff) << ifor(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;				//逐个点亮LED
		Delay(60000);
	}
	for(i = 1;i <= 8;i++)
	{
		P0 = ~(0xff << i);			//逐个熄灭LED
		Delay(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;		//计数初值为50ms
	TL0 = (65535 - 50000) % 256;
	
	ET0 = 1;		//使能定时器T0
	EA = 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();
	}
}
	

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenShift 4 - 在单节点的 OpenShift 上用 NFS Operator 实现以 RWX 访问存储

《OpenShift / RHEL / DevSecOps 汇总目录》 文本已在 OpenShift Local 4.12 环境中进行验证。 文章目录OpenShift 支持的存储访问模式用 NFS Provisioner Operator 实现 RWX 访问存储安装 NFS Operator解决安装 Operator 过程无法访问谷歌 gcr.io 上的容器镜像配置 NFSProvisi…

《零基础学机器学习》读书笔记三之基本机器学习术语

《零基础学机器学习》读书笔记三之基本机器学习术语 一、机器学习快速上手路径&#xff08;续&#xff09; 1.3 基本机器学习术语 1.3.1 特征 特征是机器学习中的输入&#xff0c;原始的特征描述了数据的属性。特征的维度指的是特征的数目。 把向量、矩阵和其他张量的维度统…

React脚手架应用(二)

1、react脚手架 脚手架简介 用来帮助程序员快速创建一个基于xxx库的模板项目 1、包含了所有需要的配置&#xff08;语法检查、jsx编译、devServer…&#xff09;&#xff1b; 2、下载好了所有相关的依赖&#xff1b; 3、可以直接运行一个简单效果&#xff1b; create-react-a…

加速企业数字化进展,小程序容器来帮忙

近年来&#xff0c;由于新冠疫情&#xff0c;诸多企业面临经济挑战&#xff0c;高效办公常常无法正常保证。在此期间&#xff0c;不少企业纷纷加快了数字化进展。 2021年&#xff0c;在Gartner新型技术成熟度曲线中我们看到&#xff1a;组装式应用、实时事件中心即服务、生成式…

软考高级系统架构师背诵要点---系统安全与系统可靠性分析

系统安全与系统可靠性分析 系统安全&#xff1a; 信息摘要、数字签名、数字信封 被动攻击&#xff1a;收集信息为主&#xff0c;破坏保密性 窃听&#xff1a;用各种可能的合法手段和非法手段窃取系统中的信息资源和敏感信 业务流分析&#xff1a;通过对系统进行长期的监听&a…

Spark08: Spark Job的三种提交模式

一、三种任务提交方式 1. 第一种&#xff0c;standalone模式 基于Spark自己的standalone集群。指定–master spark://bigdata01:7077 2. 第二种&#xff0c;是基于YARN的client模式。 指定–master yarn --deploy-mode client 使用场景&#xff1a;这种方式主要用于测试&am…

Homekit智能家居DIY-智能通断开关

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

自定义archetype脚手架完整步骤与异常情况处理方案

自定义archetype脚手架完整步骤与异常情况处理方案一、创建模板项目二、生成骨架jar包三、骨架安装到本地仓库如果出现安装位置错误的情况&#xff0c;参考以下场景处理&#xff1a;四、选择骨架&#xff0c;创建新项目创建项目时&#xff0c;如果一直卡在Generating project i…

Java集合(七)LinkedHashSet

LinkedHashSet的全面说明&#xff1a; &#xff08;1&#xff09;LinkedHashSet是HashSet的子类 &#xff08;2&#xff09;LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组双向链表 HashSet为数组单向链表 &#xff08;3&#xff09;LinkedHashSet根据元素的has…

Redis基础篇:Redis常见命令与数据结构

文章整理自B站黑马视频课程第一章&#xff1a;Redis数据结构介绍一&#xff1a;五种常见基本类型二&#xff1a;三种不常见类型第二章&#xff1a;数据类型的使用一&#xff1a;Redis通用命令二&#xff1a;String类型1&#xff1a;String常见命令2&#xff1a;String常见命令实…

任务系统的程序设计

任务是程序应用中常见的系统&#xff0c;它有助于用户代入角色&#xff0c;也有助于研发、运营和用户的互动&#xff0c;通常完成任务之后会给予用户一定的奖励。1&#xff0c;基本数据结构早期的任务系统设计的都很简单&#xff0c;大部分都是线性结构&#xff0c;偶尔会有环任…

负载均衡-

常见的负载均衡系统包括 3 种&#xff1a;DNS 负载均衡、硬件负载均衡和软件负载均衡。 DNS 负载均衡 DNS 是最简单也是最常见的负载均衡方式&#xff0c;一般用来实现地理级别的均衡。例如&#xff0c;北方的用户访问北京的机房&#xff0c;南方的用户访问深圳的机房。DNS 负…

【FreeRTOS】详细讲解FreeRTOS中事件(event)并通过具体示例讲述其用法

文章目录事件函数解析示例事件 事件&#xff0c;实际上是一种任务间通信的机制&#xff0c;主要用于实现多任务间的同步&#xff0c;其只能是事件类型的通信&#xff0c;无数据传输。与信号量不同的是&#xff0c;它可以实现一对多&#xff0c;多对多的同步。即可以是任意一个事…

为什么data属性是一个函数而不是一个对象?

一、实例和组件定义data的区别 vue实例的时候定义data属性既可以是一个对象&#xff0c;也可以是一个函数 const app new Vue({el:"#app",// 对象格式data:{foo:"foo"},// 函数格式data(){return {foo:"foo"}} }) 组件中定义data属性&#x…

MACD二次金叉选股公式,零轴上下、一次三次金叉举一反三

本文介绍了MACD二次金叉选股公式编写思路&#xff0c;以MACD零轴之下二次金叉为例&#xff0c;编写选股公式&#xff0c;进行信号过滤&#xff0c;并把选股公式改编为技术指标。此外举一反三&#xff0c;介绍了三次金叉以及MACD零轴上二次金叉。 一、MACD二次金叉选股公式编写 …

ECharts线性渐变色示例演示

第003个点击查看专栏目录Echarts的渐变色采用了echarts.graphic.LinearGradient的方法&#xff0c;可以根据代码中的内容来看如何使用。线性渐变&#xff0c;多用于折线柱形图&#xff0c;前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1&#xff0c;相当于在图形包围盒中的百分…

计算机图形学 第10章 真实感图形

目录 学习目标 前情提要 # RGB颜色模型 HSV颜色模型 CMYK颜色模型/印刷颜色模型 简单光照模型&#xff08;考&#xff09;⭐⭐⭐ 简单光照模型假定&#xff1a; 材质属性 环境光模型 漫反射光模型 镜面反射光模型 Phong反射模型: 光强衰减 增加颜色 光滑着色 直线段的…

CentOS 7.9安装zabbix6.0LTS版本

环境说明 这里使用为 CentOS 7.9版本进行测试验证&#xff0c;zabbix Server 采用源码包部署&#xff0c;数据库采用 MySQL8.0版本&#xff0c;zabbix-web使用 &#xff0c;nginxphp来实现。 具体信息如下&#xff1a; 软件名版本zabbix-server6.0.12LTSzabbix-agent6.0.12LT…

MySQL数据库的常见考点

文章目录1、ACID事务原理事务持久性事务原子性MVCC基本概念MVCC基本原理undo logundo log版本链readviewMVCC实现原理RC读已提交RR可重复读MVCC实现原理总结2、并发事务引发的问题3、事务隔离级别4、索引4.1、索引概述4.2、索引优缺点4.3、索引结构二叉树B-Tree树BTree树BTree优…

测试组合生成器-allpairspy

1、前言 在我们写功能用例时&#xff0c;常常会遇到多个参数有很多的选项&#xff0c;而如果想把这些参数值都要覆盖执行的话&#xff0c;工作量可想而知。那有没有什么办法既可以减少用例数量&#xff0c;也可以保证用例质量又降低测试时间成本&#xff0c;本篇将介绍一款工具…