蓝桥杯模块学习2——LED灯

第一章 硬件部分

1.1 为什么要了解硬件部分?

  比赛的时候会给出原理图,如果我们能够深入的理解硬件,就可以从中推导出代码应该怎样写,而不用死记硬背

1.2 电路的组成部分

1.2.1 74HC573锁存器

  1. 原理图:
    ​​​​​​​​​​在这里插入图片描述
  2. 功能:
    (1)LE控制锁存,由Y4C控制(可以简单理解为开关,当LE为高电平时,Dx和Qx之间的通道就打开)
    (2)D0-D7确定改变的数据,其中D0-D7与Q0-Q7一一对应,由单片机P0决定(正输出——不管之后输入什么数据,之后都保持输出之前输入的数据)

1.2.2 SN74HC02DRG4四路二输入或非门

  1. 原理图:
    ​​​​​​​​​​在这里插入图片描述

  2. 功能:集成了四个二输入或非门的模块,其中A、B为输入,Y为输出
    ​​在这里插入图片描述

1.2.3 74HC138译码器

  1. 原理图:在这里插入图片描述
  2. 功能:实现用A0-A2控制Y0-Y7,其中对应方式是以二进制与十进制的对应方式,如100控制Y4=0,其他都为1(反输出)

1.3 整体电路理解

  我们要将所有电路结合起来看,就可以有一个大概的控制LED流程:

  1. 首先我们通过P0口传入LED控制数据
  2. 寻根溯源:由74HC573锁存器图可知,LED锁存器由Y4C控制;又由四路二输入或非门图可知,Y4C由Y4和WR控制;又由74HC138译码器图可知,Y4由P27、P26、P25控制。(至于WR我们就不用管了,J13是板子外接的排针,由跳帽短接决定,其中涉及到MM模式我们之后再说,现在我们可以默认它接到GND,即与0相或,对结果没有影响)
  3. 由以上两点分析可知,LED控制由P0和P27、P26、P25决定:
    (1)其中LED另一端接到VCC,即P0中为低电平的IO口对应的LED亮
    (2)P27、P26、P25分别为100,即选择Y4

第二章 具体实验

2.1 实验内容

  使八个LED灯顺序点亮,然后再顺序熄灭,最后全部闪三下(每个要加适当的延时)

2.2 无操作系统代码

注:一开始接触可以就写这个代码,过省赛应该是没问题的

2.1.1 按照以上思路写的代码

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#define u8 unsigned char
#define u16 unsigned int
sbit HC138_A2=P2^7;
sbit HC138_A1=P2^6;
sbit HC138_A0=P2^5;

void LED_LE_ON();
void LE_OFF();
void Buzzer_LE_ON();
void Delay_1ms(u16 num);
// 主函数
void main(void)
{
	u8 i;
  while(1)
  { 
		//关闭蜂鸣器
		Buzzer_LE_ON();
		P0=0x00;	
		LED_LE_ON();
		//顺序点亮
		for(i=0;i<=8;i++)
		{
			P0=0XFF<<i;
			Delay_1ms(100);
		}
		Delay_1ms(800);
		//顺序熄灭
		for(i=0;i<=8;i++)
		{
			P0=~(0XFF<<i);
			Delay_1ms(100);
		}
		Delay_1ms(800);
	  //全部连续闪三下
    for(i=0;i<3;i++)
		{
			P0=0x00;
			Delay_1ms(300);
			P0=0xff;
			Delay_1ms(300);
		}		
		Delay_1ms(800);
		LE_OFF();
  }
}

void LED_LE_ON()
{
	HC138_A2=1;
	HC138_A1=0;
	HC138_A0=0;
}
void Buzzer_LE_ON()
{
	HC138_A2=1;
	HC138_A1=0;
	HC138_A0=1;
}
void LE_OFF()
{
	HC138_A2=0;
	HC138_A1=0;
	HC138_A0=0;
}

// 延时函数,大概时间
void Delay_1ms(u16 num)
{
  unsigned int i;
  while(num--)
    for(i=0; i<628; i++);
}

2.1.2 模块化

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#define u8 unsigned char
#define u16 unsigned int
void Delay_1ms(u16 num);
void Close_All(void);
void LED_ON(u8 L_X);

// 主函数
void main(void)
{
	u8 i;
	Close_All();
  while(1)
  { 
		//顺序点亮
		for(i=0;i<=8;i++)
		{
			LED_ON(0XFF<<i);
			Delay_1ms(100);
		}
		Delay_1ms(800);
		//顺序熄灭
		for(i=0;i<=8;i++)
		{
			LED_ON(~(0XFF<<i));
			Delay_1ms(100);
		}
		Delay_1ms(800);
	  //全部连续闪三下
    for(i=0;i<3;i++)
		{
			LED_ON(0x00);
			Delay_1ms(300);
			LED_ON(0xff);
			Delay_1ms(300);
		}		
		Delay_1ms(800);
  }
}

/*
	输入变量:P0口的对应的16进制数
	输出变量:无
	功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
	P0 = L_X;
	P2 = (P2 & 0x1f) | 0x80;
	P2 &= 0x1f;//用完就关,随手关门从我做起
}

// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
  unsigned int i;
  while(num--)
    for(i=0; i<628; i++);
}

/*
	输入变量:无
	输出变量:无
	功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
	//关闭蜂鸣器和继电器
	P0 = 0x00;
	P2 = (P2 & 0x1f) | 0xA0;
	P2 &= 0x1f;
	//关闭LED灯
	P0 = 0xff;
	P2 = (P2 & 0x1F) | 0x80;
	P2 &= 0x1f;	
}

2.1.3 使用了更复杂的位操作

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "reg52.h"
#define u8 unsigned char
#define u16 unsigned int

void Delay_1ms(u16 num);
void Close_All(void);
void LED_ON(u8 L_X);
void LED_ON_Lx(u8 L_X);
u8 last_led = 0xff;
// 主函数
void main(void)
{
	u8 i;
	Close_All();
  while(1)
  { 
		//顺序点亮
		for(i=0;i<=8;i++)
		{
			LED_ON_Lx(i);
			Delay_1ms(100);
		}
		Delay_1ms(800);
		//顺序熄灭
		for(i=0;i<=8;i++)
		{
			LED_ON_Lx(i);
			Delay_1ms(100);
		}
		Delay_1ms(800);
	  //全部连续闪三下
    for(i=0;i<3;i++)
		{
			LED_ON(0x00);
			Delay_1ms(300);
		  LED_ON(0xff);
			Delay_1ms(300);
		}		
		Delay_1ms(800);
  }
}

/*
	输入变量:P0口的对应的16进制数
	输出变量:无
	功能:选择相应的锁存器后,通过P0口控制LED灯亮
*/
void LED_ON(u8 L_X)
{
	P0 = L_X;
	P2 = (P2 & 0x1f) | 0x80;
	P2 &= 0x1f;
}

/*
	输入变量:Lx灯翻转
	输出变量:无
	功能:选择相应的锁存器后,通过P0口控制某个LED灯翻转,但不影响其他LED灯
	注意:使用前要对last_led进行宏定义
*/
void LED_ON_Lx(u8 L_X)
{
	//由于P0口是公用的口,我们要对每次点灯的数据进行记录,不然会受其他操作的影响
	P0 = last_led ^ (0x01<<(L_X-1));
	last_led = P0;
	P2 = (P2 & 0x1f) | 0x80;
	P2 &= 0x1f;
}

// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
  unsigned int i;
  while(num--)
    for(i=0; i<628; i++);
}

/*
	输入变量:无
	输出变量:无
	功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
	//关闭蜂鸣器和继电器
	P0 = 0x00;
	P2 = (P2 & 0x1f) | 0xA0;
	P2 &= 0x1f;
	//关闭LED灯
	P0 = 0xff;
	P2 = (P2 & 0x1F) | 0x80;
	P2 &= 0x1f;	
}

2.3 RTX51代码

国赛必备,优点是可以在延时的时候畅通无阻的执行其他东西

#include <rtx51tny.h>
#include <STC15F2K60S2.H>
#define u8 unsigned char
#define u16 unsigned int	
u8 l_data;
void All_Close();
void LED_Show(u8 l_data);
void Startup() _task_ 0
{
	All_Close();
	os_create_task(1);
	os_create_task(2);
	os_delete_task(0);
}

void task1() _task_ 1
{
	static u8 i;
	while(1)
	{
		for(i=0;i<=8;i++)
		{
			l_data = 0xff<<i;
			os_send_signal(2);
			os_wait2(K_IVL,100);
		}
		os_wait2(K_IVL,800);
		
		for(i=0;i<=8;i++)
		{
			l_data = ~(0xff<<i);
			os_send_signal(2);
			os_wait2(K_IVL,100);
		}		
		os_wait2(K_IVL,800);
		for(i=0;i<3;i++)
		{
			l_data = 0x00;
			os_send_signal(2);		
			os_wait2(K_IVL,500);
			l_data = 0xff;
			os_send_signal(2);		
			os_wait2(K_IVL,500);
		}
		os_wait2(K_IVL,800);
	}
}

void task2() _task_ 2
{
	while(1)
	{
		os_wait1(K_SIG);
		LED_Show(l_data);
	}
}
/******************************/

//选择锁存器,输出数据
void Select(u8 cs,u8 s_data)
{
	P0 = s_data;
	P2 = P2 & 0x0f | (cs<<5);
	P2 &= 0x0f;
}

//关闭外设
void All_Close()
{
	//关闭蜂鸣器
	Select(5,0x00);
	//关闭LED
	Select(4,0xff);	
	//关闭数码管
	Select(7,0xff);		
}

//输入8位数据亮灯,1为亮灯
void LED_Show(u8 l_data)
{
	Select(4,~l_data);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数码管是一种常见的数字显示器件,可以用于显示各种数字、字母等字符。在单片机应用中,数码管通常用于显示计数器、计时器、温度、湿度等实时数据。 数码管的种类有很多,包括共阳数码管、共阴数码管、共阳共阴混合数码管等。其中,共阳数码管是最常见的一种,也是本文所涉及的数码管类型。 单片机控制数码管的原理是通过对数码管的各个管脚进行控制,使其显示相应的数字或字符。数码管的控制方式有两种,即静态显示和动态显示。 静态显示是指将要显示的数字或字符的每一位分别输出到数码管的每个管脚上,然后使其保持不变,从而实现显示效果。静态显示的缺点是需要使用大量的I/O口,且不能灵活地改变显示内容。 动态显示是指将要显示的数字或字符的每一位依次输出到数码管的每个管脚上,并在短时间内快速切换下一个数字或字符,从而形成连续的显示效果。动态显示的优点是可以使用较少的I/O口,且可以灵活地改变显示内容。 以下是一个简单的动态显示数码管的实现示例: 1. 定义数码管的引脚 ```c #define DIG_PORT P2 // 数码管位选端口 #define DIG_COM 0x00 // 数码管位选端口初始值 #define LED_PORT P0 // 数码管段选端口 ``` 2. 定义数码管显示的数字或字符 ```c unsigned char code ledChar[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; ``` 3. 实现数码管动态显示函数 ```c void display(unsigned char i) { unsigned char j, k; for (j = 0; j < 8; j++) { DIG_PORT = DIG_COM | (1 << j); // 选择数码管位(从左到右) for (k = 0; k < 100; k++); // 延时,视情况可调整 LED_PORT = ledChar[i]; // 显示数码管上的数字或字符 } } ``` 4. 调用数码管动态显示函数 ```c int main() { unsigned char i = 0; while (1) { display(i % 10); // 显示数字 i 的个位数 i++; } return 0; } ``` 以上就是一个简单的数码管动态显示的实现示例。需要注意的是,数码管的控制方式和具体实现方法可能因不同的硬件平台和编程语言而有所不同。因此,在具体应用中需要根据实际情况进行适当的调整和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值