十四、基础技能综合实训案例解析

目录

自己实现有问题的部分:

①跑马管(左到右依次点亮数码管的所有段码(怎么实现数码管全亮?),再依次从左  到右熄灭)

②独立按键:按下按键,灯没反应、数码管暂停?(松开正常)

③串口(没写)

代码(除去串口):


设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。

①设计系统初始化函数,关闭蜂鸣器和继电器等无关设备。

②设计设备检测函数,首先检测LED指示灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。

③系统从上电开始显示系统运行时间,从00时00分00秒开始,显示格式:watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

④八个LED指示灯分为2组:L1~L4为远程控制组,L7~L8为本地控制组。

    远程控制组的指示灯由上位机通过串口发送命令控制开关,本地控制组的指示灯由独立按      键控制开关。按键检测需做去抖动处理,松开有效,按键S5控制L7,按键S4控制L8

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16  

0000 0001   

0000 0011

0000 0111

自己实现有问题的部分:

①跑马管(左到右依次点亮数码管的所有段码(怎么实现数码管全亮?),再依次从左  到右熄灭)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

②独立按键:按下按键,灯没反应、数码管暂停?(松开正常)

P0口是复用的,即用P0口控制灯光,又用P0口控制数码管,而P0口在不断更新数码管状态

将LED当前状态读取出来,watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_18,color_FFFFFF,t_70,g_se,x_16

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6KGM5LiN5Zyw5LiK,size_20,color_FFFFFF,t_70,g_se,x_16

③串口(没写)

 

代码(除去串口):

#include "reg52.h"

sfr AUXR = 0x8e;

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;

sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned char code SMG_duanma[18] = {
	//  0   1    2    3    4    5    6    7
		0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
	//  8   9    A10  B11  C12  D13  E14  F15
		0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
	// -16  .17
		0xbf,0x7f};  //共阳数码管

unsigned char stat_led = 0xff;//定义LED灯当前开关状态(全灭)

void InitHC138(unsigned char n)//选Y
{
	switch(n)
	{
		case 4://LED
			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;
	}
}

//*****①系统初始化函数,关闭蜂鸣器和继电器等无关设备******************
void InitSystem()
{
	InitHC138(5);
	P0 = 0x00;//关闭蜂鸣器和继电器
	InitHC138(4);
	P0 = stat_led;//***保存LED初始状态***
	InitHC138(0);
}
//******************************************************************


//*****②设备检测****************************************************
void Delay(unsigned int t)
{
	while(t--);
	while(t--);
}

void CheckLED() 
{
//检测LED指示灯,从L1~L8依次逐个点亮,再依次逐个熄灭
	unsigned char i;
	InitHC138(4);
	for (i = 1; i <= 8; i++)
	{
		P0 = 0xff << i;
		Delay(60000);
	}
	for (i = 1; i <= 8; i++)
	{
		P0 = ~(0xff << i);
		Delay(60000);
	}
}

void CheckSMG()
{	
//检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭
	unsigned char i;
	InitHC138(7);
	P0 = 0x00;          //点亮数码管的所有段码
	
	for (i = 0; i < 8; i++)
	{
		InitHC138(6);
		P0 = ~(0xfe << i);//逐个点亮数码管(熄灭取反)
		Delay(60000);
	}
	
	for (i = 0; i < 8; i++)
	{
		InitHC138(6);
		P0 = 0xfe << i;		//逐个熄灭数码管 1111 1110
		Delay(60000);
	}
	InitHC138(0);
}
//******************************************************************


//*****③系统从上电开始显示系统运行时间,从00时00分00秒开始************
unsigned char count = 0;
unsigned char t_shi = 0;
unsigned char t_fen = 0;
unsigned char t_miao = 0;

void InitTimer0()//定时器0中断函数(每50ms产生一次中断)
{
	TMOD = 0x01;
	TH0 = (65535 - 50000) / 256;//1s = 1000ms = 100 0000us = 20*50000us 
	TL0 = (65535 - 50000) % 256;//每50ms产生一次中断(1s = 20*50ms)
	
	ET0 = 1; 
	EA = 1;
	TR0 = 1;//打开定时器
}

void ServiceTimer0() interrupt 1 //中断服务函数
{
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	
	count++;
	if (count == 20)
	{
		t_miao++;
		count = 0;
		if (t_miao == 60)
		{
			t_fen++;
			t_miao = 0;
			if (t_fen == 60)
			{
				t_shi++;
				t_fen = 0;
				if (t_shi == 99)
				{
					t_shi = 0;
				}
			}
		}
	}
}

void SMG_bit(unsigned pos, unsigned char dat)//数码管位置、数据
{
	InitHC138(6);
	P0 = 0x01 << pos;
	InitHC138(7);
	P0 = dat;
}

void DelaySMG(unsigned char t)
{
	while(t--);
}

void SystemTime()//上电开始显示系统运行时间
{
	SMG_bit(0, SMG_duanma[t_shi/10]);
	DelaySMG(100);
	SMG_bit(1, SMG_duanma[t_shi%10]);
	DelaySMG(100);
	
	SMG_bit(2, SMG_duanma[16]);
	DelaySMG(100);
	
	SMG_bit(3, SMG_duanma[t_fen/10]);
	DelaySMG(100);
	SMG_bit(4, SMG_duanma[t_fen%10]);
	DelaySMG(100);
	
	SMG_bit(5, SMG_duanma[16]);
	DelaySMG(100);
	
	SMG_bit(6, SMG_duanma[t_miao/10]);
	DelaySMG(100);
	SMG_bit(7, SMG_duanma[t_miao%10]);
	DelaySMG(100);
}

void DelayS(unsigned char t)
{
	while(t--)
	{
		SystemTime();
	}
}

//******************************************************************


//*****④八个LED分为2组:L1~L4为远程控制组,L7~L8为本地控制组**********
void InitUart()//串口中断函数
{
	TMOD = 0x20;
	TH1 = 0xfd;
	TL1 = 0xfd;
	TR1 = 1;
	
	SCON = 0x50;
	AUXR = 0x00;
	
	ES = 1;
	EA = 1;
}

void ServiceUart() interrupt 4 //中断服务函数
{
	
}

void ScanKeys()//L1~L4为远程控制组,L7~L8为本地控制组
{
//去抖动处理,松开有效
	
	if (S5 == 0)//按键S5控制L7
	{
		DelaySMG(100);
		if (S5 == 0)
		{
			while(S5 == 0) //等待按键S5松开(没有结束,不能空等待)
			{
				SystemTime();//等待的同时不断刷新数码管,否则数码管就会停在这里
			}
			InitHC138(4);
			stat_led = (stat_led | 0x40) & (~stat_led | 0xbf);
			P0 = stat_led;// (1111 1111 | 0100 000)&(0000 0000 | 1011 1111)
			InitHC138(0); //        1011 1111 & 1011 1111 = 1011 1111(S7亮)
		}
	}
	
	if (S4 == 0)//按键S4控制L8
	{
		DelaySMG(100);
		if (S4 == 0)
		{
			while(S4 == 0) //等待按键S4松开(没有结束,不能空等待)
			{
				SystemTime();//等待的同时不断刷新数码管,否则数码管就会停在这里
			}
			InitHC138(4);
			stat_led = (stat_led | 0x80) & (~stat_led | 0x7f);
			P0 = stat_led;// (1111 1111 | 1000 000)&(0000 0000 | 0111 1111)
			InitHC138(0); //        0111 1111 & 0111 1111 = 0111 1111(S8亮)
		}
	}
}
//******************************************************************

void main()
{
	InitSystem();
	CheckLED();
	CheckSMG();
	InitTimer0();
	while(1)
	{
		SystemTime();
		ScanKeys();
	}
}

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行不地上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值