LED的电路图
先通过38译码器选择Y4C位,再给P0引脚赋值-----共阳极的LED灯,给相应位号提供低电平即可点亮该位号的LED灯,闪烁使用延时,流水灯使用延时+移位
打开锁存器P2=0x80(记忆方法有8个LED灯)
LED的控制方法
1.字节/位赋值
(实现点亮L1 L3 L7 L8四个LED,其余熄灭)
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); /* 关闭蜂鸣器、继电器*/
}
void vDevice_Ctrl(unsigned char p2data,unsigned char p0data)
{
P0 = p0data;
P2 = p2data;
P2 = 0;
} /*后面有优化的代码*/
void main(void)
{
vSystem_Init();
vDevice_Ctrl(0x80,0x3a); /* 点亮L1 L3 L7 L8四个LED,其余熄灭 */
vDevice_Ctrl(0x80,0xaa); /* 点亮L1 L3 L5 L7四个LED,其余熄灭 */
while(1)
{
}
}
2.标志位控制
(实现点亮L1 L3 L7 L8四个LED)
先设一数组变量,大小为9位,为了方便和不易出错,1~8分别对应8个LED。
再把需控制位置1,P2口是取反。
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
unsigned char led_ctrl[9];
void vDevice_Ctrl(unsigned char p2data,unsigned char p0data)
{
P0 = p0data;
P2 = p2data;
P2 = 0;
}
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); /* 关闭蜂鸣器、继电器*/
}
void main(void)
{
vSystem_Init();
led_ctrl[1]=1;led_ctrl[3]=1;led_ctrl[7]=1;led_ctrl[8]=1; /* 点亮L1 L3 L7 L8四个LED */
vDevice_Ctrl(0x80,~(led_ctrl[8]<<7 | led_ctrl[7]<<6 | led_ctrl[6]<<5 | led_ctrl[5]<<4 |
led_ctrl[4]<<3 | led_ctrl[3]<<2 | led_ctrl[2]<<1
|led_ctrl[1]));
while(1)
{
}
}
结果和上图一样,不占用篇幅赘述。
流水灯的实现
L1~L8 流水形式亮
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
unsigned char led_ctrl[9];
/**
* @brief 系统初始化函数:关闭继电器、蜂鸣器
* @param None
* @retval None
* @author dianshe.taobao.com
*/
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); /* 关闭蜂鸣器、继电器*/
}
void vLED_Running_L1_L8(void)
{
static unsigned char led_shift=0;
vDevice_Ctrl(0x80,~(0x01<<led_shift));
led_shift++;
if(led_shift==8) led_shift=0;
}
void vLED_Running_L8_L1(void)
{
static unsigned char led_shift;
vDevice_Ctrl(0x80,~(0x80>>led_shift));
led_shift = (led_shift + 1) % 8;
}
void vLED_Running_L2_L4_L6_L8(void)
{
static unsigned char led_shift;
vDevice_Ctrl(0x80,~(0x02<<led_shift));
led_shift = (led_shift + 2) % 8;
} //%8 让它循环
void main(void)
{
vSystem_Init();
led_ctrl[1]=1;led_ctrl[3]=1;led_ctrl[7]=1;led_ctrl[8]=1; /* 点亮L1 L3 L7 L8四个LED */
vDevice_Ctrl(0x80,~(led_ctrl[8]<<7 | led_ctrl[7]<<6 | led_ctrl[6]<<5 | led_ctrl[5]<<4 |
led_ctrl[4]<<3 | led_ctrl[3]<<2 | led_ctrl[2]<<1 | led_ctrl[1]));
while(1)
{
vLED_Running_L2_L4_L6_L8();
vDelay_Ms(200); /* 仅作练习用,在while(1)不要使用大于20ms的延时!会造成CPU资源浪费! */
/* 学完定时器,即可把长时间Delay给优化掉! */
}
}
LED流水灯(简版)
运用共用体实现优化
1.共用体(Union
)是一种特殊的数据类型,
它允许在同一个内存位置存储不同的数据类型。
共用体的所有成员共享同一块内存空间,
因此同一时间只能存储其中一个成员的值。
共用体的定义和结构体类似,使用关键字union
,后面跟着成员列表。
每个成员可以是不同的数据类型,
但共用体的所有成员都共享同一块内存空间,大小取决于最大的成员。
2.在LED中就可以使用
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
/* 用typedef定义一个叫bits的结构体“数据类型”, 从而可以用 bits b; 定义b为结构体的“变量”*/
typedef struct
{
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
}bits;
/* 用typedef定义一个叫HexToBin的共用体“数据类型”, 从而可以用 HexToBin led_ctrl; 定义led_ctrl为共用体的“变量”*/
typedef union
{
unsigned char hex;
bits b;
}HexToBin;
HexToBin led_ctrl,buzzer_ctrl;
/**
* @brief 系统初始化函数:关闭继电器、蜂鸣器
* @param None
* @retval None
* @author dianshe.taobao.com
*/
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); /* 关闭蜂鸣器、继电器*/
}
void main(void)
{
vSystem_Init();
led_ctrl.hex = 0x55; /* 对led_ctrl进行“字节赋值”,希望L2 L4 L6 L8点亮 */
vDevice_Ctrl(0x80,led_ctrl.hex); /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成点亮L2 L4 L6 L8操作 */
buzzer_ctrl.b.b4 = 1; /* 对buzzer_crtl进行“位赋值”,希望吸合继电器 */
vDevice_Ctrl(0xa0,buzzer_ctrl.hex); /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成吸合继电器操作 */
while(1)
{
led_ctrl.b.b1 = 1; /* led_ctrl进行“位赋值”,希望熄灭L2 */
vDevice_Ctrl(0x80,led_ctrl.hex); /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成熄灭L2操作 */
buzzer_ctrl.b.b4 = 1; /* 对buzzer_crtl进行“位赋值”,希望吸合继电器 */
vDevice_Ctrl(0xa0,buzzer_ctrl.hex); /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成吸合继电器操作 */
vDelay_Ms(200); /* 仅作练习用,在while(1)不要使用大于20ms的延时!会造成CPU资源浪费!学完定时器,即可把长时间Delay给优化掉! */
led_ctrl.b.b1 = 0; /* led_ctrl进行“位赋值”,希望点亮L2 */
vDevice_Ctrl(0x80,led_ctrl.hex); /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成点亮L2操作 */
buzzer_ctrl.b.b4 = 0; /* 对buzzer_crtl进行“位赋值”,希望关闭继电器 */
vDevice_Ctrl(0xa0,buzzer_ctrl.hex); /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成关闭继电器操作 */
vDelay_Ms(200);
}
}
使用共用体可以清晰的知道LED的运作原理,也方便后续的代码查错。强力推荐使用,后面的代码量会比较大,使用它不用重复定义变量。