找回密码
 注册
关于网站域名变更的通知
查看: 328|回复: 6
打印 上一主题 下一主题

怎么实现流水模式?

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-12-9 10:28 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
刚学习单片机这门课程,现在要做个流水灯实验。我编辑的代码为什么只能逐个点亮然后八个全亮完。而不是实现一亮七灭往复循环的流水灯模式呢?是少了哪一步吗?请教各位,谢谢。1 s3 ]; x9 n5 l, b! q  j% \

# @) P# ]# D+ ]" W: T; b
# g, w, q; T9 {& J& L6 Q' w
9 j3 H9 O  A0 r

该用户从未签到

2#
发表于 2022-12-9 11:19 | 只看该作者
循环一次后要给P0口重新赋值。

该用户从未签到

3#
发表于 2022-12-9 13:30 | 只看该作者
找个例程看看吧,程序结构有问题,赋值就是给端口或变量一个值,你程序里也有先给端口赋值
头像被屏蔽
  • TA的每日心情
    奋斗
    2022-11-8 15:10
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    4#
    发表于 2022-12-9 14:27 | 只看该作者
    提示: 作者被禁止或删除 内容自动屏蔽
  • TA的每日心情
    开心
    2025-3-27 15:54
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    5#
    发表于 2022-12-9 17:29 | 只看该作者
    本帖最后由 pigdragon 于 2022-12-9 17:49 编辑 ) [4 O: I: l. ?( F

    . R7 r1 ^% \2 j; {( K" X你程序几个错误.
    5 D6 z9 S: B% a5 U-----------------9 @* \+ a/ q/ r" l& I9 |
    你的亮灯全部亮错了,你说好歹有一次灯亮对了,是不是?不,你的第一次是第二个灯亮(D1灯),而不是引脚0的第一个灯亮.我们分析如下:: D9 _/ p3 k0 o$ ?3 C% u% f7 S1 k
    你的语句是P0=P0<<1;该语句在循环体中实际执行效果写下来应当是:4 F* w2 S, c  U  B
    -
    , ]$ B, D# G4 ]; ?" G0 P' @第1次,索引i是0:原来的P0是1111 1110,新的P0赋值:1111 1100 ' @" a, j( B. [4 I) g
    第2次,索引i是1:原来的P0是1111 1100,新的P0赋值:1111 1000  N- b" F' w. Q' J7 k5 z; m3 \
    第3次,索引i是2:原来的P0是1111 1000,新的P0赋值:1111 0000) J2 y$ v6 `/ m- Z
    ....
    / f8 I8 J* z0 F& _第6次,索引i是5:原来的P0是1100 0000,新的P0赋值:1000 0000
    ) n, r$ U* ~( Q) O/ T5 _; J! ~第7次,索引i是6:原来的P0是1000 0000,新的P0赋值:0000 0000: p3 ~5 n0 [9 C
    -你这里有错误,索引应该是7,不应该开始下一个for循环(是i<=7哦,不是i<7)
    9 P& X3 c7 H; Z第8次,索引i是7:原来的P0是0000 0000,新的P0赋值:0000 0000. X. n2 J3 }. c) X( w, [; c' {
    -正常的话下面是新的循环开始,但是,因为代码的while(1)内部P0在for循环后再执行for循环的时候P0没有被改变过,所以P0以后一直是0x0了.+ O( o, l4 d/ M. j& c
    第9次,索引i是0:原来的P0是0000 0000,不在改变,新的P0赋值:0000 0000也不再改变.
    $ ~$ p$ t8 w; A' D! ?* }* Q.......9 V8 d; O) j4 R% o0 X, O( h, p' U
    所有灯全亮,不再改变.; Y5 l2 y' I! T/ {) L& H3 W# `% c; Y
    ------
    0 _4 i- \6 t2 _) d  r
    + p" _+ a9 `3 Y0 c* L% S& G, w-怎么修改呢?
    8 h, P7 W) @5 L( o0 O. i! N5 N---------------------
    / |% S1 x- z2 L% Q/ T搞不明白怎么做的话,就像我上面的写的分析,要用笨办法,当然笨办法是最可靠的办法.就是手动写出过程,我们应当这样做:8 `* o% e# R# S7 ?3 S( j9 V" E
    原理图属于低电平亮的电路,这样每次让一个引脚为低电平即可点亮,下一次让下一个引脚为低电平,其它为高电平.0 K/ c& H9 Z. K) s# Q
    第1次,索引i应为0,P0输出应该为1111 1110)b = 0xFE,D7亮
      R2 S; z, ]' }' X( T第2次,索引i应为1,P0输出应该为1111 1101)b = 0xFD,D1亮  ......奇怪,灯的编号??. G) M: p0 S* n; l5 r- m! w
    第3次,索引i应为2,P0输出应该为1111 1011)b = 0xFB,D2亮
    ! I& U" f4 h! x3 m1 e9 o4 R, p....
    * M) P* G% x3 Y8 g( c第8次,索引i应为7,P0输出应该为:(0111 1111)b =0xEF,D8亮.
    # M( t' k7 |/ K第9次,,索引i应为8?不,应该重新开始点亮第一个灯D7,此时所以i应该置为0,当然也有别的方法不管它继续执行,也可以满足要求.
    9 |* u$ f& s/ s# w其中:
    7 P7 O! b# t% Q) L7 Z8 m第1次很重要,第8次很重要,第9次也很重要,为什么呢?2 o3 m% @8 A, D+ K. \  F) w/ C
    第1次是起始状态,你应该满足它的工作条件; / a  T' f0 A, U5 w; f  G
    第8次是结束状态,你应该满足它的工作条件;9 G# l# W, n( g$ r2 [
    学习微积分这些高等数学的时候,我们一天到晚确认边界条件,因为边界条件很重要,我们做一些事情的时候,需要根据情况,一会儿这么干,一会儿那么干,所有的事归类为开始条件,干法,结束条件,它们是一个整体,任何一个条件错,整体都是错的.如果第一次条件和干法与循环体内的条件,不一致的时候,单独列出单独完成;同样,结束时的条件和干法也如此." o$ p; L2 Z8 O7 h% r
    第9次是重新开始循环的状态,你应该重新返回初始边界,要执行"重设初始条件"的动作,满足它的工作条件,所有的程序员都犯过在跳回重新开始循环的时候漏了执行循环所需要的初始条件的事,造成错误.  7 `; w, O/ M% Q5 \) j/ ?* i5 D
    --------------------------------------------------------------0 O8 w: j) _- S; [3 n
  • TA的每日心情
    开心
    2025-3-27 15:54
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    6#
    发表于 2022-12-9 17:33 | 只看该作者
    本帖最后由 pigdragon 于 2022-12-9 18:08 编辑   _  o/ |, R2 t1 L7 j/ L

    ( I2 Y% K7 i: B) v8 J. q: b这样根据上面的分析结果,根据你用的0xFE,程序应该这样:' u* S7 ]# B& Q5 U8 w8 q8 }- M
    第一次0=0xFE
    ( }0 o# T+ o( b1 M$ |) L第二次0=(P0<<1)+1
    $ Q9 F- Q- Y) M$ J第三次0=(P0<<1)+1
    , Q& o6 Y! i0 U3 q+ v! P+ t. @& z...6 K, @% o% S* p, u' n' D
    第八次:P0=(P0<<1)+1
    ' I* n4 D% ~2 g3 r; l' r2 V5 g4 q所以,对于笨办法,或者我工作很忙,没时间仔细分析改进,或者这里不是性能核心,不需要优化执行,我就把代码分为两部分执行,第一部分是第一次执行,第二部分是第2步到第8步.代码如下
    $ c' U. R& q) R& B' Wwhile(1)
    : G8 s. f/ l: E, g  K, T{
    ) R% C; J; H! e! T2 s; [        //第一步:
    & ~% g; ^- Q' S        i=1;% z3 B! {6 R. S6 Z7 B
            P0=0xFE;( g; N9 r7 D9 B/ \) ]. m" |6 n! J
            //第二步到第八步:/ }- ]! a% n( P! P- @2 L1 F
            for(i=2;i<=8;i++)" A8 r. C( H6 O) D7 F; f
            {$ ?5 h& g: }! H4 O$ F; y% H" f  l$ E
                    P0=(P0<<1)+1;
    8 S% h6 D) Y7 g& z                delay(10);
    4 q, J& E! o0 e' K3 h" j' t        }
    4 H2 X" s6 b8 S- p6 u}
    4 k# F" W6 s9 }! y/ G7 |这里P0放在循环体内了,因为我们的这两个部分代码干的是同样一件事,就是第一次和后面不一样而已,两部分构成了一次循环的完整事务.所以千万不要把P0的第一次放在循环体外面.
    % u7 `. A6 l. L! D0 F对了吗?还有错误,因为所有的事情都归为开始条件,干法,结束条件;我们第一步设置P0=0xFE的时候,我们的干法没有结束呢!还要delay(10)才算第一次执行的事情干完呢,代码应该这样:0 {# z. `. A% S0 Q5 K( d( N3 }
    while(1)1 u! |+ _9 G8 u% b
    {
    . u. T2 q% N) B4 H1 @& C; a        //第一步:
    4 b8 D# A3 j. l* w        i=1;
    ( {1 o  `1 k7 n; V: k        P0=0xFE;
    , S) v* w+ |9 K( g- T; _        delay(10); //有了delay才算第一步干完呐.
    2 b6 S* v0 h+ x3 _- P) v        //第二步到第八步:7 d2 V1 U; A9 B2 P+ Y
            for(i=2;i<=8;i++)
    - ^# j! Y0 E. k- B! u" q9 B        {9 s5 Z$ W( z  u8 B% ^
                    P0=(P0<<1)+1;6 h7 d  `# t' Q' X# J
                    delay(10);$ H# ~, N4 j6 F/ Y3 B1 n
            }3 @, @. K; d) W( [* ~6 r
    }8 O3 ]6 Q1 z) ?& D, }6 m
    后面我们可以再优化,也可以不管,反正正确了,那个i=1;表示第一次执行的代码放在那里没啥用,编译器也会自动丢弃它的(你要开启优化才可以).放在那里还能让我再看代码的时候好理解$ \* X6 y& Q' c) g0 u6 B
  • TA的每日心情
    开心
    2025-3-27 15:54
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    7#
    发表于 2022-12-9 17:39 | 只看该作者
    本帖最后由 pigdragon 于 2022-12-9 17:58 编辑
    % Y$ N. Q+ N" j* l' U5 g( [- L! W) o2 J* O' j0 S
    鉴于我们对位操作的理解,可以观察到应该输出为(0x01 <<第x次)的按位取反.我们可以优化一下,把上面的两个部分的工作和为一个:
    + @3 j7 k7 t4 x4 o* C) C5 w9 ?; u$ RP0=~(0x01<<i);( x/ \5 l% k6 M7 O  U6 R: _. M
    给你这种萌新翻译一下:
    - T2 n' O, J; P8 c; z第1次:i=0; 0x01左移0位,二进制是0000 0001,按位反是:1111 1110
    - G7 e( ~) a8 r( @第2次:i=1; 0x01左移1位,二进制是0000 0010,按位反是:1111 1101
    5 h8 [% _) L: j* y6 m第3次:i=0; 0x01左移2位,二进制是0000 0100,按位反是:1111 1011, D2 x  h9 d0 u6 Z; a+ A4 T& D. M
    ...
    3 I0 ]' b& ^0 p3 ?第8次:i=7; 0x01左移7位,二进制是1000 0000,按位反是:0111 1111
    - \1 h" o6 s. D. s2 ~# i. e7 D4 e  H' K/ \: H
    因为所有的从开始到结束都不依赖老的P0的值,操作方式完全一样,第一步和后面都是一样的代码,就完全合并了.7 x7 k; w! H/ a- j6 N  f
    代码如下:: ^$ q8 H1 I$ [9 X( V! M
    void main()
    / }4 n8 l+ R4 Z7 _  j  y, o{
    2 R5 D: V, j6 a% X        int i;% P& F4 b# T' |
            P0=0xFF;   //所有灯都灭.当然是废话,不需要的.P0每次都是单独设置,不依赖上次的P0
    , g: M. p! N; J2 b        //也P0=0xFF是废话,当然也更不需要delay了.
    " k$ ^4 Q% |% q. J/ R  O3 f        while(1)
    6 k# B5 s4 W: k9 @: p8 I9 m+ P9 O        {        
    : j& u) n3 c& {3 I# g5 H                for(i=0;i<8;i++)  //是8不是7哦,另外,可以写成i<=7
    / O  E  Q+ n/ C! ]. _                {
    ( \6 g3 t! o: S8 n                        P0 = ~(0x01 <<i);
    ' i- R) u8 T: P$ n9 @                        delay(100);        //时间长点,做实验的话10毫秒太短了.4 X* `+ j" s4 R  I
                    }
    , h8 J! d6 f0 X6 g( z$ C        }- R5 \0 L" s. V  h

    2 v" w* p9 S& z( {}
    * ]& p% d. k/ Z) s7 U2 H' E........汗,限制我发帖,增补到这个帖子里:
    , h+ E. `" G( a+ O/ T-----------------------------------------------------------5 p' N6 W1 I) {0 \4 y
    当然我用过这样的,通常我用在循环缓冲区里的技巧,需要我循环缓冲区为256字节或者2的整数次方,歪个楼列出来,你思考一下
    # J9 ~4 P5 e  y# Z6 \) F# F; A
      ~  c8 X) z: y; y, y1 {void main()
    6 ^. K2 o9 j: ^1 ~/ p7 [; g) Q{
    / J" I# u; E+ {# j8 y; H0 c5 a        unsigned char i;' S- m# C0 s1 ^) E* X; Q
            i=0;7 }" o" e' _" Q7 D4 v* Q" S
            while(1)6 i5 `& L9 C7 `4 Y1 l/ I; x
            {          d6 I, Q1 [; J/ ?. p" m1 u
                    P0 = ~(0x01 <<(i & 0x07));
    3 V9 k' Y0 s. h* v! J                delay(100);% ~: H7 o* u! f2 q
                    i++;
    5 ]* o/ R4 v; _' x1 \        }( t* m2 w, H- e- ?1 n2 ?
    ) z* ]0 E/ t! b
    }8 S$ u6 k7 Z: U2 C

    * n3 i% H" ]8 D) X* R9 d还可以这样,可上述代码已经让别人讨厌了,下面的我自己都讨厌:
    # a& K  E! S! I# _4 l+ r5 wvoid main(), P3 g: H2 o3 a2 i5 c1 \1 D/ _) G
    {
    1 A! E7 g& x4 T6 ?- f        unsigned char i;9 @$ E/ e6 H% u: o9 L+ B
            i=0;$ r1 g' t) N) L! r
            while(1)
    % `1 A8 Q4 w' v8 y( T! E        {        2 E! H, ?$ o/ [9 O6 m
                    P0 = ~(0x01 <<((i++) & 0x07));
    % P8 o- g$ b. T# z# ]; X1 Z                delay(100);
    & i  U0 w' x- U' {) s/ [        }
    5 N+ E9 }+ _& u, N; X* V/ R) s/ s* M+ P7 x4 J: ~) [2 u, ]  y+ o
    }/ B/ n- U" s  E6 ^0 o

    + n0 [" b3 X3 a反正都是常规操作了,知道了就知道了,看你萌新,给你些经验/ `' T5 }- E0 b% B& e
    6 d% y, e! A6 y5 q5 Y7 W! B

    ! y1 [2 ~1 n6 p( _0 f" {
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-8-20 17:37 , Processed in 0.140625 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表