{:soso_e183:} |
学习了,顶一个 |
jianhong_wu 发表于 2015-1-22 23:06 多谢鸿哥夸奖! |
本帖最后由 重庆-风雪 于 2015-1-26 22:26 编辑 流水灯与呼吸灯结合-滴水灯 --基于朱兆琪51学习板 何为滴水灯? 模拟水滴形成并且滴落下 模拟过程 水滴形成:LED亮度从暗到亮 滴落过程:普通流水灯带拖尾效果 何为空间替换时间? 用空间替换时间,某些数据运算的时候会占用CUP和时间,我们可以在之前把这些结果写出来,到时候直接读取就是了,而且还增加了可读性,因为不用去看计算的过程。 滴水灯如何实现 水滴形成的过程跟呼吸灯一样,所以不多做概述。 我们直接看流水灯带拖尾效果,这时候我们需要做的就是同时让几颗 LED显示不同的亮度,也就是我们要同时输出几组不同的占空比。先来 看看这样输出八组不同的占空比行不行: /************ 主循环部分 *****************/ code unsigned char LightLevel[8]={0,1,2,4,8,16,32,64};//定义8个亮度级别 unsigned char i = 0; unsigned char j = 0; unsigned char k = 0; unsigned char temp = 0xFF; while(1) { for(i = 0; i < 64; i++) { /* 里面的for循环更新8颗LED亮灭状态 */ for(j = 0; j < 8; j++) { if(LightLevel[j] <= i) { /* 达到条件,点亮第j颗LED */ temp |= (1 << j); } else { /* 未达条件,熄灭第j颗LED */ temp &= ~(1 << j); } } DriveLED(temp); } } 先来分析一下程序,里面的一个for循环根据外面一个for循环的变量i和亮度等级表比对,计算出LED亮灭状态,然后通过DriveLED()驱动LED。不管i的值是多少,LightLevel[0] <= i都成立,那么第一颗LED就是一直都亮的,只有当i等于63的时候,LightLevel[7] <= i才成立,所以8颗LED是根据亮度表来调节占空比的,从理论上来说,这个程序是可行的,但是实际上行不行呢?答案是不行!为什么呢? 就像上一节提到的,595驱动LED需要消耗一定的时间,数据运算也要消耗一定的时间,虽然每一次执行的时间很少,但是累加起来就足以影响效果了,在上一节中,是通过减小总循环的次数来解决的,但是这次不行,循环次数不能减小了。怎么办呢?我记得朱老师在讲课的时候,曾经讲过一个概念, 用空间替换时间,这些数据运算的结果无非就是在不同的时刻显示不同的LED,显示次数多的就亮一点,次数少的就暗一点,我们可以在之前把这些结果 写出来,到时候直接读取就是了,而且还增加了可读性。 代码如下: #include <reg52.h> #include "DriveLED.h" /* 第几个元素表示亮几颗LED */ code unsigned int uiCntLEDTab[16]= { 0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x00FF, 0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,0xFFFF, }; /****************************************************** * 函数名称:main * 函数功能:主函数 * 入口参数:NULL * 出口参数:NULL *******************************************************/ int main() { unsigned char i; /* 函数的初始化 */ InitLED(); /* 主循环 */ while(1) { for(i=0; i < 32; i++) { DriveLED(uiCntLEDTab[i / 2]); } } return 0; } 下到板子的结果是完美输出了16组不同的占空比!而且一看就明白了,不像上一段代码,各种for循环嵌套,头都看晕了!会了这一步,滴水灯基本上就出来了! 滴水灯代码: /****************************************************** * 程序名称:main.c * 程序功能:实现滴水灯的主程序文件 * 程序作者:TWAS * 创建时间:2015-1-22 * 修改时间:2015-1-24 * 程序版本:V0.1 ******************************************************/ /* 包含的头文件 */ #include <reg52.h> #include "DriveLED.h" #include "delay.h" /* 第一个元素表示亮几颗LED */ code unsigned int uiCntLEDTab[5]= { 0x0001,0x0003,0x0007,0x000F,0x001F }; /* 亮度等级 */ code unsigned char ucLightLevelTab[5] = { 32,16,8,4,1 }; /****************************************************** * 函数名称:main * 函数功能:主函数 * 入口参数:NULL * 出口参数:NULL *******************************************************/ int main() { unsigned char i,j,k,time,ucNum = 0; /* 函数的初始化 */ InitLED(); /* 主循环 */ while(1) { /* 水滴形成 */ while(1) { time = 2; while(time--) /* 此循环控制每一个状态保持的时间,可以改变水滴形成的速度 */ { for(i = 0; i < 50; i++) { /* 通过修改ucNum的值,就可以改变占空比 */ if(i < ucNum) { DriveLED(0x8000); /* LED驱动点亮D16 */ } else { DriveLED(0x0000); /* LED驱动,熄灭所有 */ } } } ucNum++; if (ucNum==50) { break; } } /* 拖尾效果 */ /* 最外层for循环控制水滴滴下的过程,k的值表示这5组占空比位于16颗LED的哪一个位置 */ for (k = 15; k >= 0 && k <= 15; k--) { time = 2; while(time--) /* 此循环控制每一个状态保持的时间,可以改变水滴滴落的速度 */ { for (i = 0; i < 5; i++) { for (j = 0; j < ucLightLevelTab; j++) { /* 根据ucLightLevelTab[]选择LED点亮次数 */ DriveLED(uiCntLEDTab << k); } } } } InitLED(); while(1); } return 0; } /****************************************************** * 程序结束 *****************************************************/ |
有图有代码,绝对是精品。{:soso_e179:} |
|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )
GMT+8, 2024-11-29 18:22 , Processed in 0.208025 second(s), 22 queries .