这是一个非常短的呼吸灯程序
本帖最后由 doujiang 于 2013-3-24 16:10 编辑呼吸灯,肯定很多人都写过,这里是一个简短的呼吸灯程序。#include <STC12C5A.H>
#define uchar unsigned char
#define uint unsigned int
#define limit 100
sbit LED=P0^4;
void delay(uint ms)
{
uint i=0,j=0;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
void main()
{
uint t=50;
char d=1;
while(t+=d)
{
LED=t%2;
delay(t*(LED==1)+(limit-t)*(LED==0));//这条代码很巧妙的实现了两个状态的切换
if(t>=95||t<=5) d=-d;
}
}
ok,试试看 MARK 记号一下 好像挺有意思 试试,我也来呼吸一下 收下了,可以试试{:victory:} 刚写了一个带ADC调呼吸速度的,还没收到钱
真的没法跟这个软件比。 我看了半天,没看懂,谁给解释下。。。 好 留着 思路不错。
如果LED为1,则t有效。为0则limit-t有效。
这样调节亮和灭的占空比。
当t上升到大于等于95的时候d就d=-d。d就变负数。t+-d=t-d。t下降。下降到小于等于5时d=-d。则变正。又上升 先标记,有机会试验下 e315 发表于 2013-3-25 00:29 static/image/common/back.gif
我看了半天,没看懂,谁给解释下。。。
程序有三个亮点,第一:用%2来实现LED灯的两种状态的切换。第二:用逻辑判断等实现了延时与LED灯状态的匹配。第三:边界条件的判断以及d=-d实现了呼吸灯的由灭逐渐到亮,再由亮逐渐到灭。这个可以想象成球撞击墙面的物理模型。 这个程序,没有考虑执行的效率,只考虑代码的简洁。 马克 试一试 试一下。记号。 有时间也试试! 谁能想出来同样简洁的风吹蜡烛的效果? mark!{:handshake:} 有机会试试 mark一下 为什么不用三元运算符实现?这个不算巧妙吧。 记下,,分享一下 简洁但效率不高 记号一下先 试下看,看来挺好玩. tiancaigao7 发表于 2013-3-26 08:24 static/image/common/back.gif
为什么不用三元运算符实现?这个不算巧妙吧。
三元运算符实际上也是if语句的缩写式,但是这个程序里的方法完全就用加法和逻辑运算代替了if语句,是一个我们不常用到的方式。 MARK,程序真够简洁的 MARK 非常短的呼吸灯程序,学习这种写法。 谢谢分享! doujiang 发表于 2013-3-25 23:38 static/image/common/back.gif
程序有三个亮点,第一:用%2来实现LED灯的两种状态的切换。第二:用逻辑判断等实现了延时与LED灯状态的匹 ...
谢谢你的回复,我编译了下,这个要生成这么大的代码,代码效率感觉太低了。。。
Program Size: data=11.0 xdata=0 code=183
另,while(t+=d) 这个语句,我觉得用while(1)也可以呀,可以烧下却不能运行, 是为什么呢? 效果能够实现,已经移植到定时中断里,但是亮的过程和灭的过程时间不一样。在定时中断里,就不用考虑效率了吧 本帖最后由 takashiki 于 2013-3-27 15:41 编辑
doujiang 发表于 2013-3-26 12:16 static/image/common/back.gif
三元运算符实际上也是if语句的缩写式,但是这个程序里的方法完全就用加法和逻辑运算代替了if语句,是一个 ...
你这个还是用到了判断,而且比三元运算符更多……,LED == 0 和 LED == 1 都是判断
真要Kill掉判断,应该这样写:delay(t*LED+(limit-t)*(1 - LED));
不好意思,写成这样已经非常变态了。更变态一点,就是将括号里面展开,代替编译器进行计算,变成delay((t*2-limit) * LED + limit - t),可以少掉一次乘法,不过这样写不作注释基本上是看不懂了。
由于用到了16位的乘法,它的开销比逻辑运算要大得多,因此采用这种所谓的“技巧”根本是不可取的。 takashiki 发表于 2013-3-27 15:29 static/image/common/back.gif
你这个还是用到了判断,而且比三元运算符更多……,LED == 0 和 LED == 1 都是判断
真要Kill掉判断,应 ...
这个,你只考虑到这条代码在呼吸灯里的运用,但是如果状态有三种以上呢?不用逻辑判断就不行了。这个代码只是提供给大家一个新的思路,用这种方法可以实现if,else,else....的替换,前面也提到过,只考虑了代码的简洁,没有考虑性能哈! 对应搞单片机的人来说,不该光看C的长度,还有关注下编译后的汇编长度吧 mark 谢谢分享谁有更好的 代码 贴出来大家互相学习啊 cqsrmxxzyx 发表于 2013-3-27 19:17 static/image/common/back.gif
对应搞单片机的人来说,不该光看C的长度,还有关注下编译后的汇编长度吧
这个没有考虑执行效率,只考虑的代码简洁程度哈,只是提供给大家一个代替ifelse else......的方式,况且如果你仔细考虑后,会发现这种方法还可以用在很多其它地方,并不只是在单片机上,主要还是给大家一个另一种思路 围观一下 思路很有意思!收了! 有时间可以试试 比较巧妙 MARK一下 MARK 非常短的呼吸灯程序,学习这种写法。 不错从效果上来说 没写过,看看 doujiang 发表于 2013-3-27 19:09 static/image/common/back.gif
这个,你只考虑到这条代码在呼吸灯里的运用,但是如果状态有三种以上呢?不用逻辑判断就不行了。这个代码 ...
N多个状态一样可以用超长的表达式来解决,数学上有一种术语叫做分段函数,一般情况下我们是将它们按照自变量的取值范围分成若干段,然后组合而成,这样就有多个函数式。但也有人非得把各种分段都统一到一条语句中去,这样既长又不好理解。
用数学的观点来解决计算机的问题是不对的,数学可以用来解决计算机的问题,但是纯数学的观点只会走弯路。
下面我举一个例子,把简单问题复杂化,很复杂,一步一步的进行复杂,也是我所不推崇的
这么一个简单函数,他只完成这么个功能,计算一个Byte的十进制数有多少位:unsigned char TestFunc(unsigned char x){
return (x >= 100) ? 3 //大于等于100的具有3位数字
: (x >= 10) ? 2 // 10~99的具有2位
: 1; // 0~9只有1位
}现在我们将它复杂化,使用数学上的分段函数表述,这里有三个区间,分别是, , ,因为是离散的,我都写成闭区间了,如果是连续的(比如实数),那就必须要写成半开半闭。
首先考虑区间,结果是3,得到如下表达式,为了书写方便,我用y表示返回值:
y = 3 * ((x + 156) >> 8);
x + 156在x>=100是会产生进位,而<100则不会,因此 ((x + 156) >> 8)在大于等于100时是会等于3的,上述表达式成立。
接来下,我就要计算x<100的值了,因为上述表达式在x<100时只能等于0。
继续考虑,分段的第二段,x为区间。
显然: y = 2 * ((x+246) >> 8) 是会在这个区间上成立的,但是当x>=100时,它也仍然成立,因此需要去除。去除后的结果是: y = 3 * ((x + 156) >> 8) + (1 - ((x + 156) >> 8)) * ( 2 * ((x+246) >> 8));好了,分段2完成,以此类推,直至完成。 y = 3 * ((x + 156) >> 8) + (1 - ((x + 156) >> 8)) * ( 2 * ((x+246) >> 8)) + (1 - ((x + 246) >> 8)) * 1;N段的一样这样完成,你看我连一个判断都没有,但是这个有什么意义呢?不写注释能看懂的都是神人。难道就是你所谓的一种方法? 如果楼主喜欢收集各种技巧,那我再给你一个技巧吧,只在51上可用,效果那是非常明显,不过看得人要骂人就是了。
P1.0在y>=x时输出高电平,y<x时输出低电平,那么可以写作:P1_0 = (ACC = x - y, CY);哈哈,这个如何?代码特别短,效率特别高。 takashiki 发表于 2013-3-28 12:58 static/image/common/back.gif
如果楼主喜欢收集各种技巧,那我再给你一个技巧吧,只在51上可用,效果那是非常明显,不过看得人要骂人就是 ...
谢谢啦!!!{:lol:} 什么是呼吸灯? 本帖最后由 doujiang 于 2013-3-28 15:15 编辑
takashiki 发表于 2013-3-28 12:31 static/image/common/back.gif
N多个状态一样可以用超长的表达式来解决,数学上有一种术语叫做分段函数,一般情况下我们是将它们按照自 ...
这个,只是说提供给大家一个新的方式,并不是说它有多好多好,我在这里提出来,大家看到后,可能会想:哦...原来还可以用这种方式来代替if语句,那如果我没提出来,那估计很多人都不晓得有这样的办法,现在讨论的不是说它的实际的执行效率啥的,而是说这是一个也许大家从来没见过的新的方式而已。我也深知代码短,并不代表执行效率高,就像求1000000000内素数的个数一样,往往那些在很短时间内求出个数的程序代码是非常长的,因此,这里只是提出一个新的方法哈。 程序有三个亮点,第一:用%2来实现LED灯的两种状态的切换。
%2如果编译器不做优化的话,效率很低。还不如&1,效果是一样的.
这样的程序,虽然看来简洁,但读起来难懂,执行效率也不高.在工程是不值提倡 这个可以试试啊 用硬件PWM输出是不是更简单? 效果不是太好,闪烁得厉害 学习了学习了 mark一下,学习下 看看怎样? 学习一下 看看,是不是挺美的 mark!学习了,的确很简洁!有空玩玩! 有长见识了,呼吸灯!! 最好用中断吧。。 没有见过这样的C语言语法呀,符合C标准吗? mark 一下 要是很多灯呼吸怎么办? 非常简洁!有个语句头次见到过! 本帖最后由 15813191501 于 2013-5-8 13:12 编辑
删了吗?看不到了?电脑上可以看到程序,手机上看不到。 有资料吗? 很有想法啊 先记下来先 MARK 非常短的呼吸灯程序,学习这种写法。 很好,收藏了 回家再玩 刚试过程序可行,不过延时时间有点长,一直在闪,延时改小一点 效果更好! inkfish321 发表于 2013-3-26 00:42谁能想出来同样简洁的风吹蜡烛的效果?
什么叫风吹蜡烛? 谢谢分享 mark 记下学习一下。 虚心学习了 有点意思,顶 好东西,先保存 呼吸灯~~~~~~~~~~~~~~~~~~~ 自带PWM的单片机更短 厉害!!!效果非常棒!!! 思路很有意思 很巧妙。。。。。。。。。 这技巧,短小精悍! 标记下 回头试验一下 思路很巧妙 怎么想出来的{:kiss:} mark
来自:amoBBS 阿莫电子论坛 Windows Phone 8 客户端 试一试。。 mark 不错,mark 果然很简洁,试试看! 学习了,马克 回去试一下 回去试一下 回去试一下 mark,谢谢分享! 呼吸不是指数上升、下降的吗?线性升降效果也能达到那么好的效果吗?
页:
[1]
2