【蓝桥杯单片机学习记录4】小蜜蜂老师的工厂灯光设计程序代码赏析——博采众长

今天是第一个综合的代码,用到了LED、数码管、串口、定时器等模块

用到的程序主要有延时、初始化、流水灯、573的选择、单个数码管显示数据、时间显示、定时器的初始化和中断函数、串口初始化和中断函数、串口数据解析函数、独立按键

代码如下:

#include "reg52.h"

void Delay();                            //普通延时函数
void DelaySMG();                        //数码管延时函数
void SelectHC573();                          //寄存器选择

void DisplaySMG_Bit();                     //数码管显示指定数据
void DisplayTime()();                        //时间显示

void InitTimer0();                         //定时器初始化

void InitUart();                            //串口初始化

void SendByte();                            //单字节发送数据
void ExecuteCommand();                    //数据解析函数
void ScanKeys();                            //按键扫描

void check_LED();                            //LED灯测试
void check_SMG():                            //数码管测试
void InitSystem();                          //系统初始化,关闭无关设备

sfr AUXR = 0x8e;							//定义辅助寄存器
sbit S5 = P3^2;								//定义按键S5引脚
sbit S4 = P3^3;								//定义按键S4引脚

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 stat_led = 0xff;		//定义LED灯当前开关状态
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
	  0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x900x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//共阳数码管的段码编码表

/*==================普通的延时函数======================*/
void Delay(unsigned int t)
{
	while(t--);
	while(t--);
}
/*================数码管专用延时函数====================*/
void DelaySMG(unsigned int t)
{
	while(t--);
}
/*=================锁存器选择函数======================*/
void SelectHC573(unsigned channel)
{
	switch(channel)
	{
		case 4:P2 = (P2 & 0x1f) | 0x80;		//Y4输出0,选择LED控制
		break;
		case 5:P2 = (P2 & 0x1f) | 0xa0;		//Y5输出0,选择蜂鸣器和继电器控制
		break;
		case 6:P2 = (P2 & 0x1f) | 0xc0;		//Y6输出0,选择数码管位选
		break;
		case 7:P2 = (P2 & 0x1f) | 0xe0;		//Y7输出0,选择数码管段码
		break;
		case 0:P2 = (P2 & 0x1f) | 0x00;		//所有锁存器不选择
		break;
	}
}
/*=================单个数码管显示函数====================*/
void DisplaySMG_Bit(unsigned char value, unsigned char pos)
{
	P0 = 0xff;						//消隐
	SelectHC573(6);
	P0 = 0x01 << pos;			//数码管的段位		
	SelectHC573(7);
	P0 = value;						//数码管显示内容
}
/*===============系统运行时间显示函数===================*/
void DisplayTime()
{
	DisplaySMG_Bit(SMG_NoDot[t_s%10],7);		//秒个位
	DelaySMG(500);
	DisplaySMG_Bit(SMG_NoDot[t_s/10],6);		//秒十位
	DelaySMG(500);
	DisplaySMG_Bit(SMG_NoDot[16],5);				//分隔符
	DelaySMG(500);
	
	DisplaySMG_Bit(SMG_NoDot[t_m%10],4);		//分个位
	DelaySMG(500);
	DisplaySMG_Bit(SMG_NoDot[t_m/10],3);		//分十位
	DelaySMG(500);
	DisplaySMG_Bit(SMG_NoDot[16],2);				//分隔符
	DelaySMG(500);
	
	DisplaySMG_Bit(SMG_NoDot[t_h%10],1);		//时个位
	DelaySMG(500);
	DisplaySMG_Bit(SMG_NoDot[t_h/10],0);		//时十位
	DelaySMG(500);
}

/*================定时器T0初始化函数====================*/
void InitTimer0()
{
	TMOD = 0x21;			//必须注意,T0和T1的工作模式一起赋值
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	ET0 = 1;					//使能定时器T0
	EA = 1;						//使能总中断
	TR0 = 1;					//启动定时器T0
}
/*===============定时器T0中断服务函数===================*/
void ServiceTimer0() 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++;
		}
	}
}
/*=================串口初始化函数========================*/
void InitUart()
{
	TMOD = 0x21;			//必须注意,T0和T1的工作模式一起赋值
	TH1 = 0xfd;				//设置9600波特率的参数
	TL1 = 0xfd;
	TR1 = 1;					//启动定时器T1
	
	SCON = 0x50;			//8位UART模式,允许接收
	AUXR = 0x00;			//辅助寄存器设置(89C82系列不需要)
	
	ES = 1;						//使能串口中断
	EA = 1;						//使能总中断
}
/*=================串口中断服务函数====================*/
void ServiceUart() interrupt 4
{
	if(RI == 1)
	{
		command = SBUF;		//将接收到的数据保存到command变量
		RI = 0;						//将接收完成标志RI清0
	}
}
/*=================串口发送单字节函数====================*/
void SendByte(unsigned char dat)
{
	SBUF = dat;   //将数据放进SBUF缓冲器
	while(TI == 0);
	TI = 0;
}
/*===============上位机命令解析执行函数==================*/
void ExecuteCommand()
{
	if(command != 0x00)							//接收到一个上位机命令
	{
		switch(command & 0xf0)				//将命令类型取出来
		{
			case 0xa0:									//远程灯光控制命令
				SelectHC573(4);
				stat_led = (stat_led | 0x0f) & (~command | 0xf0);
  //0x0f用二进制表示为00001111    0xf0用二进制表示为11110000,这种方式可以保证只改
  变前四位而不影响后四位。遇到这种情况的写法:先让受控制的位为0,写出来十六进制;再让不受控制位
  为0,写出来十六进制;先让变量本身和第一个数取反;再让给的命令和第二个数取反;最后相与
				P0 = stat_led;
				SelectHC573(0);
				command = 0x00;                    //清零
			break;
			
			case 0xb0:									//读取现场系统运行时间命令
				SendByte((t_h / 10 << 4) | (t_h % 10));//BCD码所以要移4位
				SendByte((t_m / 10 << 4) | (t_m % 10));
				SendByte((t_s / 10 << 4) | (t_s % 10));
				command = 0x00;
			break;
		}
	}
}
/*=================独立按键扫描函数====================*/
void ScanKeys()
{
	if(S5 == 0)							//发现按键S5信号
	{
		DisplayTime();				//去抖动处理
		if(S5 == 0)						//确认按键S5信号
		{
			while(S5 == 0)			//等待按键S5松开
			{
				DisplayTime();
			}
			SelectHC573(4);
			stat_led = (stat_led | 0x40) & (~stat_led | 0xbf); 
			P0 = stat_led;			//执行现场灯光控制
			SelectHC573(0);
		}
	}
	
	if(S4 == 0)							//发现按键S4信号
	{
		DisplayTime();				//去抖动处理
		if(S4 == 0)						//确认按键S4信号
		{
			while(S4 == 0)			//等待按键S4松开
			{
				DisplayTime();
			}
			SelectHC573(4);
			stat_led = (stat_led | 0x80) & (~stat_led | 0x7f); 
			P0 = stat_led;			//执行现场灯光控制
			SelectHC573(0);
		}
	}
}
/*=================工厂灯光检测函数====================*/
void CheckLED()
{
	char i;
	SelectHC573(4);
	for(i = 0; i < 9; i++)
	{
		stat_led = 0xfe << i;				//逐个点亮LED灯
		P0 = stat_led;
		Delay(60000);
	}
	for(i = 0; i < 9; i++)
	{
		stat_led = ~(0xfe << i);		//逐个熄灭LED灯
		P0 = stat_led;
		Delay(60000);
	}
	SelectHC573(0);
}
/*================时间显示模块检测函数==================*/
void CheckSMG()
{
	unsigned char i;
	SelectHC573(7);
	P0 = 0x00;
	for(i = 0; i < 9; i++)
	{
		SelectHC573(6);
		P0 = ~(0xfe << i);			//逐个点亮数码管	
		Delay(60000);
	}
	for(i = 0; i < 9; i++)
	{
		SelectHC573(6);
		P0 = 0xfe << i;					//逐个熄灭数码管
		Delay(60000);
	}
	SelectHC573(0);
}
/*==================系统初始化函数======================*/
void InitSystem()
{
	SelectHC573(5);
	P0 = 0x00;
	SelectHC573(4);
	P0 = stat_led;
	SelectHC573(0);
}
/*======================主函数===========================*/
void main()
{
	InitSystem();
	CheckLED();
	CheckSMG();
	InitTimer0();
	InitUart();
	
	while(1)
	{
		ExecuteCommand();
		DisplayTime();
		ScanKeys();
	}
}

代码不是原创,是我综合几个博客整理的

看的博主:小蜜蜂老师谏书稀

想先看几个综合代码找找感觉,然后自己写几个省赛的题目,51就先放放了

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值