第一章 硬件部分
1.1 电路的组成部分
1.1.1 译码器和锁存器
具体可回顾之前LED灯的文章:
https://blog.csdn.net/weixin_63568691/article/details/130660096
1.1.2 ULN2003达林顿管
- 原理图:
- 功能:
(1)改变电路特性,以提供大电流大电压
(2)由下图可知,ULN2003是反输出
- 为什么要用达林顿管改变电路特性,不能直接用IO口像驱动LED灯一样 ,驱动蜂鸣器和继电器吗?(需要一定的电路知识)
(1)使用戴维南等效法,可将单片机IO口等效为一个5V电压源和一个十分大电阻组成的二端口网络,当外部电路接入IO口时,尽管它得到的是5V的电压,但是电流十分小,导致驱动功率即能量极小,所以除了LED灯,单片机基本都是用作控制器,而不是驱动器
(2)由于蜂鸣器和继电器需要较高的功率以支撑它们完成高频振动、产生较强的磁力,所以需要用ULN2003来驱动
1.2 整体电路理解
- 蜂鸣器驱动我们很好理解,J6的1脚没用,即跟LED的接法相同
- 至于继电器我们要先明确,VB是在蜂鸣器图中与VCC相连的,即VB=VCC,那我们就可以把继电器控制图分成两部分:
(1)当N_RELAY为电平时,继电器有电流,自动吸合
(2)当K1被吸合,与3脚相连,构成回路,L10灯亮
- 其实代码跟驱动LED类似的,只不过多了个达林顿管,P0输出高电平的引脚控制蜂鸣器或继电器工作
第二章 具体实验
2.1 实验内容
8路LED灯闪烁三次后熄灭,接着依次点亮LED灯,继电器吸合一会后断开,然后依次熄灭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;
#define buzzer 0X01<<6//相当于二进制01000000,代表P06
#define relay 0X01<<4
#define LED_LE_ON 4//相当于Y4
#define Buzzer_Relay_LE_ON 5
#define LE_OFF 0
void HC138_Y(u8 num);
void Delay_1ms(u16 num);
// 主函数
void main(void)
{
u8 i;
while(1)
{
//关闭蜂鸣器和继电器
HC138_Y(Buzzer_Relay_LE_ON);
P0=0x00;
//全部连续闪三下
HC138_Y(LED_LE_ON);
for(i=0;i<3;i++)
{
P0=0x00;
Delay_1ms(300);
P0=0xff;
Delay_1ms(300);
}
Delay_1ms(800);
//顺序点亮
HC138_Y(LED_LE_ON);
for(i=0;i<=8;i++)
{
P0=0XFF<<i;
Delay_1ms(100);
}
Delay_1ms(800);
//继电器闭合一段时间
HC138_Y(Buzzer_Relay_LE_ON);
P0=relay;//realy是宏定义的01000000,即P06
Delay_1ms(300);
P0=0x00;
Delay_1ms(800);
//顺序熄灭
HC138_Y(LED_LE_ON);
for(i=0;i<=8;i++)
{
P0=~(0XFF<<i);
Delay_1ms(100);
}
Delay_1ms(800);
//蜂鸣器鸣叫一段时间
HC138_Y(Buzzer_Relay_LE_ON);
P0=buzzer;
Delay_1ms(300);
P0=0x00;
Delay_1ms(800);
HC138_Y(LE_OFF);
}
}
/*
输入变量:4-7
输出变量:无
功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用
*/
void HC138_Y(u8 num)
{
switch(num)
{
case 4:HC138_A2=1;HC138_A1=0;HC138_A0=0;break;
case 5:HC138_A2=1;HC138_A1=0;HC138_A0=1;break;
case 6:HC138_A2=1;HC138_A1=1;HC138_A0=0;break;
case 7:HC138_A2=1;HC138_A1=1;HC138_A0=1;break;
default: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
sbit HC138_A2 = P2^7;
sbit HC138_A1 = P2^6;
sbit HC138_A0 = P2^5;
#define buzzer 0X01<<6//相当于二进制01000000,代表P06
#define relay 0X01<<4
#define LED_LE_ON 4//相当于Y4
#define Buzzer_Relay_LE_ON 5
#define LE_OFF 0
void Ouput_P0(u8 channel,u8 dat);
void Delay_1ms(u16 num);
// 主函数
void main(void)
{
u8 i;
while(1)
{
//关闭蜂鸣器和继电器
Ouput_P0(Buzzer_Relay_LE_ON,0x00);
//全部连续闪三下
for(i=0;i<3;i++)
{
Ouput_P0(LED_LE_ON,0x00);
Delay_1ms(300);
Ouput_P0(LED_LE_ON,0xff);
Delay_1ms(300);
}
Delay_1ms(800);
//顺序点亮
for(i=0;i<=8;i++)
{
Ouput_P0(LED_LE_ON,0XFF<<i);
Delay_1ms(100);
}
Delay_1ms(800);
//继电器闭合一段时间
Ouput_P0(Buzzer_Relay_LE_ON,relay);//realy是宏定义的01000000,即P06
Delay_1ms(300);
Ouput_P0(Buzzer_Relay_LE_ON,0x00);
Delay_1ms(800);
//顺序熄灭
for(i=0;i<=8;i++)
{
Ouput_P0(LED_LE_ON,~(0XFF<<i));
Delay_1ms(100);
}
Delay_1ms(800);
//蜂鸣器鸣叫一段时间
Ouput_P0(Buzzer_Relay_LE_ON,buzzer);
Delay_1ms(300);
Ouput_P0(Buzzer_Relay_LE_ON,0x00);
Delay_1ms(800);
Ouput_P0(LE_OFF,0x00);
}
}
/*
输入变量:4-7
输出变量:无
功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用
*/
void HC138_Y(u8 num)
{
switch(num)
{
case 4:HC138_A2=1;HC138_A1=0;HC138_A0=0;break;
case 5:HC138_A2=1;HC138_A1=0;HC138_A0=1;break;
case 6:HC138_A2=1;HC138_A1=1;HC138_A0=0;break;
case 7:HC138_A2=1;HC138_A1=1;HC138_A0=1;break;
default:HC138_A2=0;HC138_A1=0;HC138_A0=0;
}
}
/*
输入变量:
channel:4-7,对应Y4-Y7
dat:0-65535,P0口输出数据
输出变量:无
功能:操作138译码器,同时控制P0输出
*/
void Ouput_P0(u8 channel,u8 dat)
{
HC138_Y(channel);
P0=dat;
}
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
#define buzzer 0X01<<6//相当于二进制01000000,代表P06
#define relay 0X01<<4
#define LED_LE_ON 4//相当于Y4
#define Buzzer_Relay_LE_ON 5
#define LE_OFF 0
void Ouput_P0(u8 channel,u8 dat);
void Delay_1ms(u16 num);
void Close_All(void);
// 主函数
void main(void)
{
u8 i;
while(1)
{
//关闭蜂鸣器和继电器
Close_All();
//全部连续闪三下
for(i=0;i<3;i++)
{
Ouput_P0(LED_LE_ON,0x00);
Delay_1ms(300);
Ouput_P0(LED_LE_ON,0xff);
Delay_1ms(300);
}
Delay_1ms(800);
//顺序点亮
for(i=0;i<=8;i++)
{
Ouput_P0(LED_LE_ON,0XFF<<i);
Delay_1ms(100);
}
Delay_1ms(800);
//继电器闭合一段时间
Ouput_P0(Buzzer_Relay_LE_ON,relay);//realy是宏定义的01000000,即P06
Delay_1ms(300);
Ouput_P0(Buzzer_Relay_LE_ON,0x00);
Delay_1ms(800);
//顺序熄灭
for(i=0;i<=8;i++)
{
Ouput_P0(LED_LE_ON,~(0XFF<<i));
Delay_1ms(100);
}
Delay_1ms(800);
//蜂鸣器鸣叫一段时间
Ouput_P0(Buzzer_Relay_LE_ON,buzzer);
Delay_1ms(300);
Ouput_P0(Buzzer_Relay_LE_ON,0x00);
Delay_1ms(800);
Ouput_P0(LE_OFF,0x00);
}
}
/*
输入变量:4-7
输出变量:无
功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用
*/
void HC138_Y(u8 num)
{
switch(num)
{
case 4: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;
default:P2 = (P2 & 0x1f) | 0x00;
}
}
/*
输入变量:
channel:4-7,对应Y4-Y7
dat:0-65535,P0口输出数据
输出变量:无
功能:操作138译码器,同时控制P0输出
*/
void Ouput_P0(u8 channel,u8 dat)
{
HC138_Y(channel);
P0 = dat;
}
/*
输入变量:无
输出变量:无
功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
P2 = (P2 & 0x1f) | 0xA0;
P0 = 0x00;
}
void Delay_1ms(u16 num)
{
unsigned int i;
while(num--)
for(i=0; i<628; i++);
}
2.3 RTX51代码
国赛必备,优点是可以在延时的时候畅通无阻的执行其他东西
#include <rtx51tny.h>
#include <STC15F2K60S2.H>
#define u8 unsigned char
#define u16 unsigned int
u8 l_data=0,br_data=0;
void All_Close();
void Select(u8 cs,u8 s_data);
void LED_Show(u8 l_data);
void Buzzer_Relay_Reverve(u8 ds,u8 *br_data);
void Startup() _task_ 0
{
All_Close();
os_create_task(1);
os_create_task(2);
os_create_task(3);
os_create_task(4);
os_delete_task(0);
}
void Main_Task() _task_ 1
{
u8 i;
while(1)
{
for(i=0;i<3;i++)
{
l_data = 0xff;
os_send_signal(2);
os_wait2(K_IVL,200);
l_data = 0x00;
os_send_signal(2);
os_wait2(K_IVL,200);
}
os_wait2(K_IVL,800);
for(i=0;i<=8;i++)
{
l_data = ~(0xff<<i);
os_send_signal(2);
os_wait2(K_IVL,200);
}
os_wait2(K_IVL,800);
os_send_signal(3);
os_wait2(K_IVL,500);
os_send_signal(3);
os_wait2(K_IVL,800);
for(i=0;i<=8;i++)
{
l_data = (0xff<<i);
os_send_signal(2);
os_wait2(K_IVL,200);
}
os_wait2(K_IVL,800);
os_send_signal(4);
os_wait2(K_IVL,500);
os_send_signal(4);
os_wait2(K_IVL,800);
}
}
void LED_Task() _task_ 2
{
while(1)
{
os_wait1(K_SIG);
LED_Show(l_data);
}
}
void Relay_Task() _task_ 3
{
while(1)
{
os_wait1(K_SIG);
Select(5,br_data ^= (0x01<<4));
}
}
void Buzzer_Task() _task_ 4
{
while(1)
{
os_wait1(K_SIG);
Select(5,br_data ^= (0x01<<6));
}
}
/******************************/
//选择锁存器,输出数据
void Select(u8 cs,u8 s_data)
{
P0 = s_data;
P2 = P2 & 0x1f | (cs<<5);
P2 &= 0x1f;
}
//关闭外设
void All_Close()
{
//关闭蜂鸣器
Select(5,0x00);
//关闭LED
Select(4,0xff);
//关闭数码管
Select(7,0xff);
}
//输入8位数据,使相应的LED灯亮,1为亮
void LED_Show(u8 l_data)
{
Select(4,~l_data);
}