第一章 硬件部分
1.1 为什么要了解硬件部分?
比赛的时候会给出原理图,如果我们能够深入的理解硬件,就可以从中推导出代码应该怎样写,而不用死记硬背
1.2 电路的组成部分
1.2.1 74HC573锁存器
- 原理图:
- 功能:
(1)LE控制锁存,由Y4C控制(可以简单理解为开关,当LE为高电平时,Dx和Qx之间的通道就打开)
(2)D0-D7确定改变的数据,其中D0-D7与Q0-Q7一一对应,由单片机P0决定(正输出——不管之后输入什么数据,之后都保持输出之前输入的数据)
1.2.2 SN74HC02DRG4四路二输入或非门
-
原理图:
-
功能:集成了四个二输入或非门的模块,其中A、B为输入,Y为输出
1.2.3 74HC138译码器
- 原理图:
- 功能:实现用A0-A2控制Y0-Y7,其中对应方式是以二进制与十进制的对应方式,如100控制Y4=0,其他都为1(反输出)
1.3 整体电路理解
我们要将所有电路结合起来看,就可以有一个大概的控制LED流程:
- 首先我们通过P0口传入LED控制数据
- 寻根溯源:由74HC573锁存器图可知,LED锁存器由Y4C控制;又由四路二输入或非门图可知,Y4C由Y4和WR控制;又由74HC138译码器图可知,Y4由P27、P26、P25控制。(至于WR我们就不用管了,J13是板子外接的排针,由跳帽短接决定,其中涉及到MM模式我们之后再说,现在我们可以默认它接到GND,即与0相或,对结果没有影响)
- 由以上两点分析可知,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);
}