zysblog 发表于 2012-12-15 09:22:14

流水灯的一点儿困惑

如何用较为精悍的代码实现这个功能呢?

共有8颗LED,编号依次是1、2……8

实现目标:1流到8再1流到7再1流到6依次到全亮(10000000 、01000000……00000001、10000001、01000001……00000011、10000011、01000011……00000111依次到11111111)

如果用右移的办法不太合适,因为会冲掉右端显示的LED,如果用采用最笨的办法,代码量又很大,有没有较为简单的办法呢?

CK345 发表于 2012-12-15 09:33:53

查表{:biggrin:}

wsy2012 发表于 2012-12-15 09:36:24

一般都是查表

zb05022005 发表于 2012-12-15 09:40:55

查表比较直接

用移位的话也行,把每一轮最后的值保存一下,然后下一轮移一次位后与该值相加就可以了,就保留了先前的状态

zysblog 发表于 2012-12-15 09:42:18

wsy2012 发表于 2012-12-15 09:36 static/image/common/back.gif
一般都是查表

查表,我算了一下,很浪费空间的,比如,我有16个灯,那么就有(1+16)*16/2*2=272个字节,这太浪费空间了吧,难道有更好的查表方法吗?

zysblog 发表于 2012-12-15 09:45:36

zb05022005 发表于 2012-12-15 09:40 static/image/common/back.gif
查表比较直接

用移位的话也行,把每一轮最后的值保存一下,然后下一轮移一次位后与该值相加就可以了,就保 ...

针对这个题,查表要耗费多少字节啊?

Tliang 发表于 2012-12-15 10:37:59

int main(void)
{
        unsigned char i, j, value;
        while(1)
        {
                for(i = 0;i < 8;i++)
                {
                        value = ~(0xff >> i);
                        for(j = 0;j < 8 - i;j++)
                        {
                                P1 = (1 << j) | value;
                                delay(200);                               
                        }
                       
                }
        }
        return 0;
}int main(void)
{
        unsigned char i, j, value;
        while(1)
        {
                for(i = 0;i < 8;i++)
                {
                        value = ~(0xff >> i);
                        for(j = 0;j < 8 - i;j++)
                        {
                                P1 = (1 << j) | value;
                                delay(200);                               
                        }
                       
                }
        }
        return 0;
}

longwu537 发表于 2012-12-15 10:45:27

4楼的方法可行。当前面8次直接使用右移指令即可。后面8次采用4楼说的用sum+1<<i

longwu537 发表于 2012-12-15 10:47:18

看错了,是sum+0x80>>i

zysblog 发表于 2012-12-15 12:57:24

Tliang 发表于 2012-12-15 10:37 static/image/common/back.gif
int main(void)
{
        unsigned char i, j, value;


这是一个不错的思路,用C语言实现起来就是简单啊……

Tliang 发表于 2012-12-15 13:32:13

zysblog 发表于 2012-12-15 12:57 static/image/common/back.gif
这是一个不错的思路,用C语言实现起来就是简单啊……

汇编一样简单

xlgxufashu 发表于 2012-12-15 13:42:28

用c实现,可以有一个专门的函数

Volftooth 发表于 2012-12-15 13:54:46

无所谓浪费不浪费、单片机里面几 K 的空间不用白不用、除非你程序写满 ROM 了、我至今写过的程序没哪个是完全占完 ROM 的、最多快把 RAM 占完了、

如果你怕占多了可以做一下表的压缩、提取出相同的数值写入一个表、再用第二个表表示位置信息、或者其它方法、

Tliang 发表于 2012-12-15 14:23:44

本帖最后由 Tliang 于 2012-12-15 14:57 编辑

                ORG 00H
                LJMP MAIN
                ORG 30H

MAIN:        MOV R0,#8    ;第一个循环初值
                MOV R2,#00H       ;保留的值

LOOP1:MOV A, R0       ;第二个循环初值
                MOV R1,A       ;没有MOV Rn,Rn指令用两条指令
                MOV R3,#1       ;移位变量

LOOP2:MOV A,R3       ;先将数据移位.
                RLA               
                MOV R3,A       ;保存移位数据
                RRA               ;原来数据
      ORL A,R2       ;将保留的值或上将显示的值
                MOV P1,A       ;显示
                LCALL DELAY       ;延时
                DJNZ R1,LOOP2;继续移位
                               
                MOV A,R2       ;移位完成进行保留值计算
                RRA               ;右移一位或80H得到保留值
                ORL A,#80H
                MOV R2,A       ;保存保留值
                DJNZ R0,LOOP1;显示

                LJMP MAIN       ;大循环

                END                       ;结束
好久没用汇编了,其实主要是思路。
什么语言无所谓

lxa0 发表于 2012-12-15 15:34:11

这个还是用汇编简便~~~~~~~~~~~~~~

michaelwang333 发表于 2012-12-15 16:09:52

c用的比较习惯。

yue6315018 发表于 2012-12-16 19:43:25

michaelwang333 发表于 2012-12-15 16:09 static/image/common/back.gif
c用的比较习惯。

你看这样行不,循环次数每次减1,用右移函数,另外把每次循环的初始状态(上次循环结束时)事先存入数组,并调用。。。我,,新手

zysblog 发表于 2012-12-17 10:45:39

Tliang 发表于 2012-12-15 14:23 static/image/common/back.gif
好久没用汇编了,其实主要是思路。
什么语言无所谓

说的不错,主要是思路,我用的是PIC的汇编。你的答案给了我较大的帮助,多谢!
页: [1]
查看完整版本: 流水灯的一点儿困惑