蓝桥杯 模板Template Part4:LED
● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改
基础知识【蓝桥杯】—{模块}—{显示部分Part1:开发板初始化&LED}
一、流程图
Notes:
●对时间要求不严格的操作,如点亮、关闭、点亮一段时间,可以放在LED_Proc(void); LED处理函数
中操作;但如LED的闪烁流水等操作必须放在定时器中。
●对LED功能的实现全部借用定时器,高效、实用性高。
二、基本模板
头文件
//---------------------------LED-----------------------------------------------------//
#define L1 0X01
#define L2 0X02
#define L3 0X04
#define L4 0X08
#define L5 0X10
#define L6 0X20
#define L7 0X40
#define L8 0X80
#define All_Led 0XFF
extern uchar uc_LED;
extern void LED_ON(uchar led); //开单个LED
extern void LED_OFF(uchar led); //取反单个LED
extern void LED_Negate(uchar led); //取反单个LED
extern void LED_Disp(uchar uc_LED); //LED显示
extern void LED_Proc(void); //LED处理函数
LED.c
#include <STC15F2K60S2.h>
#include <stdio.h>
#include <intrins.h>
#include <main.h>
//-----------------------------------------单个LED开关---------------------//
void LED_ON(uchar led) //开单个LED
{
uc_LED |= led; //将某位置1
}
void LED_OFF(uchar led) //关单个LED
{
uc_LED &= ~led; //将某位置0
}
void LED_Negate(uchar led) //取反单个LED
{
uc_LED ^= led;
}
//-----------------------------------------LED显示------------------------//
void LED_Disp(uchar uc_LED)
{
//LED
P2 &= 0X1F; //关573
P0 = ~uc_LED; //预送数据
P2 |= 0X80; //开相应573
P0 = ~uc_LED; //送数据
P2 &= 0X1F; //关573
}
//-----------------------------------------LED处理函数------------------------//
void LED_Proc(void)
{
}
三、往届赛题中LED应用
四、备用模板
1、以一定频率闪烁
//以一定频率闪烁 对时间要求比较严格,必须放在定时器中
if(uc_State == 1)
{
if(!(ul_ms%500)) LED_Negate(L1);
}
2、一定时间后熄灭
Notes:
●综合往届题,可以看出,一定时间后熄灭 指的是进入某个状态,达到某个条件后开始点亮LED,一定时间后再熄灭;此时仍然是这个状态。
//-----------------------------------------LED处理函数------------------------//
void LED_Proc(void)
{
static ulong led_time2=0;
if(uc_State != 2) led_time2=0; //清零led_time2
switch(uc_State)
{
......
......
case 2: //一定时间后熄灭,进入状态2后亮10s后熄灭,检测的是进入状态2这个过程
{
if(led_time2 == 0) //第一次进入状态4
{
led_time2 = ul_ms; //记录进入时的时间
LED_ON(L2); //点亮L2
}
if(ul_ms - led_time2 >10000) //点亮时间超过10s
{
LED_OFF(L2); //关灯。但并没有清零led_time2
}
}break;
......
......
}
}
3、以一定频率闪烁一定时间
//对时间要求较为严格,放在定时器1中
static ulong led_time3=0;
if(uc_State != 3) led_time3=0; //清零led_time3
if(uc_State == 3)
{
if(led_time3 == 0) //第一次进入状态3
{
led_time3 = ul_ms; //记录进入时的时间
}
if(ul_ms - led_time3 < 10000) //计时时间<10s,闪烁
{
if(!(ul_ms%200)) LED_Negate(L3);
}
if(ul_ms - led_time3 >10000) //计时时间超过10s
{
LED_OFF(L3); //关灯。但并没有清零led_time
}
}
4、亮度等级
●PWM调光,也可以说是无级调速,高电平占多一点,也就是占空比大一点亮度就亮一点,占空比小一点亮度就没有那么亮,前提是PWM的频率要大于我们人眼识别频率,要不然会出现闪烁现象。
●一般人眼睛对于80Hz 以上刷新频率则完全没有闪烁感。频率太小的话 看起来就会闪烁。那么我们平时见到的LED灯,当它的频率大于50Hz的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,而是一个常亮的LED灯。
uchar Light_Grade; //亮度等级0到4,默认为0;通过按键调节
uchar PWM_High;
uchar PWM_Low = 4;
//以下程序放在1ms定时器中,1ms执行一次。
LED_ON(L5); //开灯5,对照亮度
if(PWM_Low>0)
{
PWM_Low--;
LED_OFF(L4);//关灯
}
else if(PWM_High>0)
{
PWM_High--;
LED_ON(L4);//开灯
}
else
{
PWM_High = Light_Grade;
PWM_Low = 4-Light_Grade;
}
Notes:
●if与else if的区别:就是if可以只要满足条件就执行,但是else if会发现即使第一个执行了,第二个满足条件依然不会执行。就像是一个互斥的现象。
5、呼吸灯
Notes:
●呼吸灯的实现与流水灯相似。
●呼吸灯即是实现PWM波的占空比从0变为1,或从1变为0。
●PWM的频率要大于我们人眼识别频率,最小大约为50Hz,即20ms。PWM的周期最大可选为PWM_T =20;
。
●PWM波的占空比变化为从1/20→2/20→3/20→4/20→5/20→……18/20→19/20→20/20
●查找人呼吸一次大约2~4s。所以每个相同占空比PWM波重复的次数为PWM_Count = 10;
。即I/O口先输出10个占空比为1/20的矩形波,再输出10个占空比为2/20的矩形波,输出10个占空比为3/20的矩形波,……输出10个占空比为19/20的矩形波,输出10个占空比为20/20的矩形波。
uchar Light_Grade; //亮度等级
uchar PWM_T =15; //pwm波的周期 ms
uchar PWM_High; //pwm波高电平时间
uchar PWM_Low; //pwm波低电平时间
uchar PWM_Count = 20; //相同占空比PWM波重复的次数
uchar PWM_Times; //相同占空比PWM波已经重复的次数
bit PWM_DTR; //pwm占空比波大小变化的方向
//以下程序放在1ms定时器内,1ms执行一次
if(++PWM_Times != PWM_Count) //一种占空比的PWM波 持续PWM_Count个
{
if(PWM_Low>0)
{
PWM_Low--;
LED_OFF(L5);//关灯
}
else if(PWM_High>0)
{
PWM_High--;
LED_ON(L5);//开灯
}
else
{
PWM_High = Light_Grade;
PWM_Low = PWM_T -Light_Grade;
}
}
else
{
PWM_Count = 2 0;
if(!PWM_DTR) if(++Light_Grade ==PWM_T) PWM_DTR^=1;
if(PWM_DTR) if(--Light_Grade == 1) PWM_DTR^=1;
}
Notes:
● if(++Light_Grade == 1)
与 if(Light_Grade++ == 1)
的区别,即为++i
和i++
的区别。
6、流水灯
见彩灯省赛题