Shop OBEX P1 Docs P2 Docs Learn Events
SX assembly code to poll a button and turn on LED — Parallax Forums

SX assembly code to poll a button and turn on LED

CraigRCraigR Posts: 12
edited 2010-02-25 23:47 in General Discussion
I am wanting to use the SX to poll a pushbutton and turn on a LED for 5 seconds when the button is pressed·using assembly code. I am confused how a "do loop"·is created in assembly code to continuously poll the pushbutton. Is there any example code on the Parallax site do perform this?

Comments

  • ZootZoot Posts: 2,227
    edited 2010-02-22 16:24
    Do the other parts of your program use an ISR (Interrupt Service Routine) or is everything in the main program?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • CraigRCraigR Posts: 12
    edited 2010-02-22 18:26
    Everything is in the main program.
  • ZootZoot Posts: 2,227
    edited 2010-02-22 18:50
    e.g.


    :startdebounceroutine
    CLR buttonCount
    :again
    MOV buttonPrev, buttonState ' load previous button state
    MOV W, #0   ' presume active low, but make 1 if button pressed
    SB ButtonPin
       MOV W, #1
    MOV buttonState, W
    XOR W, buttonPrev
    SZ
       CLR buttonCount ' if unstable, reset debounce count
    JNZ, @:again  ' if it's unstable, repeat
       INC buttonCount ' how many times stable
       CJB buttonCount, #100, @:again  ' adjust depending on clock frequency, switch noise, etc. This is 500us debounce or so at 20mhz, not much
    
    ' now the current debounced state of the button is in buttonState....
    JNB buttonState.0, @:nolight
    
    :light
      SETB LedPin
      MOV tmpB1, #200 ' these two numbers depend on clock speed, easier in an ISR, really
      MOV tmpB2, #200
    
    [img]http://forums.parallax.com/images/smilies/tongue.gif[/img]auseloop
      TEST tmpB2
      JNZ, :dec
        TEST tmpB1
        JZ, @:nolight
    :dec
      SUB tmpB1, #1
      SUBB tmpB2, /C
      JMP @[img]http://forums.parallax.com/images/smilies/tongue.gif[/img]auseloop  ' this is not printing right because the forum software doesn't like AT-COLON-PEE for some reason
    
    :nolight
       CLRB LedPin
    
    :done
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • CraigRCraigR Posts: 12
    edited 2010-02-22 22:40
    Thanks a lot that is very helpful!
  • CraigRCraigR Posts: 12
    edited 2010-02-24 17:53
    I do not need to·debounce the pushbutton. I found a sample program in the Exploring the SX pdf that uses a pushbutton with a piezoelectric speaker instead of an LED. The document says that the button is·wired to read a 0 when the button is pressed but I would like it to read a 1 when pressed. The segment of code that controls this is: jb rb.0, bwait, so jump to the "bwait" subroutine if register b is set. I changed the jb command to·jnb but the button·still reads 0 when pressed. Is there an easy way to fix this?·The program is as follows:

    device sx28l,oschs3

    device turbo,stackx,optionx

    IRC_CAL IRC_SLOW
    reset start_point
    freq 50000000 ; 50 MHz

    org 8

    second ds 2 ; counter for 1 second tone
    delay ds 1
    delay1 ds 1
    ············· org 0
    start_point·· mov !rb,#$7F ; make speaker output
    ··············call beep
    ; wait for input button
    bwait·········jb rb.0,bwait
    ··············call beep
    ············· jmp bwait
    ; subroutine
    beep··········mov second,#$d0 ; 2000 is $7D0
    ··············mov second+1,#$07
    loop········· not rb ; toggle bits
    ············· mov delay1,#24
    oloop·········clr delay
    wloop·········djnz delay,wloop
    ············· djnz delay1,oloop
    ; repeat 2000 times
    ············· djnz second,loop
    ············· djnz second+1,loop

    ············· ret ; go back to wherever

  • ZootZoot Posts: 2,227
    edited 2010-02-24 18:02
    No, it's a hardware issue. If the button is wired as "active low", i.e., it is tied to ground when pressed, then it will read as a "0" when pressed, "1" otherwise.

    You would need to adjust for this in firmware, either by setting a flag to 1 (so that regardless of how the device is wired, your code can read a "1" for a pressed button), or by changing what happens at the jump. I used the former technique in my example above. The question is -- how is your circuit actually wired?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • CraigRCraigR Posts: 12
    edited 2010-02-24 22:34
    I have a·220 ohm resistor·connected to the RB0 pin to the bottom left side of the pushbutton and·a jumper wire from Vdd connected to the upper left side of the pushbutton. A 10 kohm resistor from the top right side of the pushbutton to Vss. The LED is connected to Vss and a 470 ohm resistor connected to the RB7 pin. Is the code the same if I use a LED in place of the piezoelectric speaker that was originally used in the code? Also, I would like the pushbutton (RBO) to be my only input and the LED (RB7)·to be my only output but when I put in: mov !rb,#$01 (i.e. 00000001) the LED light comes on automatically with or without the pushbutton pressed. This code doesn't seem that complicated but I've run into many problems. I can easily code this in PBASIC for the BS2 but assembly is new to me.
  • ZootZoot Posts: 2,227
    edited 2010-02-24 23:04
    You can also code in SX/B if you like a BASIC like syntax. Examining the assembly that is "created" by the SX/B compiler might help you see how some of this stuff works.

    This will probably do something like what you want, but I didn't count the cycles in the "wait" routine so I don't know how long it is.

    device sx28l,oschs3
    
    device turbo,stackx,optionx
    
    IRC_CAL IRC_SLOW
    
    reset start_point
    
    freq 50000000 ; 50 MHz
    
    org 8
    
    second ds 2 ; counter for 1 second tone
    
    delay ds 1
    
    delay1 ds 1
    
                  org 0
    
    start_point   mov !rb,#$7F ; make led output
    
                  call flashled
    
    ; wait for input button
    
    bwait         jnb rb.0,bwait
    
                  call flashled
    
                  jmp bwait
    
    ; subroutine
    
    flashled          mov second,#$d0 ; 2000 is $7D0
    
                  mov second+1,#$07
    
                 setb RB.7
    
    loop          mov delay1,#24
    
    oloop         clr delay
    
    wloop         djnz delay,wloop
    
                  djnz delay1,oloop
    
    ; repeat 2000 times
    
                  djnz second,loop
    
                  djnz second+1,loop
    
                  clrb RB.7
    
                  ret ; go back to wherever
    
    
    
    



    Remember that moving values to !RB or !RA or !AnyPort determines whether the pin(s) are INPUTS or OUTPUTS, not whether they are "high" or "low". In the above edit, the LED is set as an output, the bwait routine waits for the button to go high. When it does, it calls the flashled routine which sets the led output pin to 1 (high), counts down some loops to "delay" the light flash, then turns the LED off again. If your button is wired as active high to RB.0 and the anode (+ lead) of your LED is wired to RB.7, this should work.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • CraigRCraigR Posts: 12
    edited 2010-02-25 13:54
    I finally got the LED to react to the pushbutton. I only need the LED to stay on after the button is pressed which it doesn't do now.
    I thought the mov·second,#$d0·and mov·second+1,#$07 would put the number 2000 into 2 memory locations and then the
    djnz·second,loop and·djnz·second+1 loop would decrement the two memory locations to stop the loop after 2000 cycles and then turn off the
    LED with the clrb·RB.7. · Does this code look correct? Is there any easier way to make the LED stay on for 2000 cycles? Any suggestions would be greatly appreciated.
  • ZootZoot Posts: 2,227
    edited 2010-02-25 14:04
    If you are not using an ISR, that's the way to "pause".

    You could also use SX/B for high-level constructs like PAUSE X and LOW Y and use assembly for other parts of your program.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • James NewtonJames Newton Posts: 329
    edited 2010-02-25 23:47
    http://www.sxlist.com/cgi-bin/delay.exe?Delay=2000&Type=cycles&Regs=d1+d2+d3+d4&clock=4&name=Delay&CPU=SX
    but change the clock=4 to clock= how ever many mega hertz your clock is actually running at.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



Sign In or Register to comment.