selective input reading

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi I'm just started a couple of weeks ago with assembly, but now I don't know how to read just 1 pin and don't look at the other pins.

I want to use PA3 as an high low input and PB0 and PB1 as output.
This is what I made so far:

Main:
;*** selection of the setting ***
in temp0,PINA
cpi temp0,$08
breq select1
cpi temp0,$00
breq select2
select1:cbi portB,0
sbi portB,1
rjmp main
select2:cbi portB,1
sbi portB,0
rjmp main

But now I look at all the pins of register A and I only want to look at pin PB3. I don't know how to do that. I thought that it was possible read PINA3 but this is not working.

I read something about masking but I'm not sure that I can use this.

Is it possible to do something like that and what do I do wrong?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which AVR is this? Is the IO address of PINA 0x00 to 0x1F? If so just use SBIS or SBIC to make a decision whether the single bit is set or clear. If the register is not in range for that opcode then you will have to IN the entire 8 bits then use ANDI with a bit mask to check the single bit.

BTW although PA3 and PB3 are both defined as "3", technically PB3 is not in the PINA register.

Oh and as for "masking". Atmel (or use with SBIS, SBIC) define the 8 bits in a register as the values 0..7, to turn this into a mask:

0 mask = 0x01
1 mask = 0x02
2 mask = 0x04
3 mask = 0x08
4 mask = 0x10
5 mask = 0x20
6 mask = 0x40
7 mask = 0x80

use the (1<<bit_number). So, for example (1<<3) is 0x08 and thus

IN R24, PINA
ANDI R24, (1 << PA3)
now branch on Z set/not set

Last Edited: Mon. Mar 29, 2010 - 01:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Main:
;*** selection of the setting ***
       in   temp0,PINA
       ANDI temp0,$08    ; only look at bit #3
       cpi  temp0,$08    ; is it set?
       breq select1      ; yes
       cpi  temp0,$00    ; obviously no
       breq select2      ;
select1: cbi portB,0
       sbi  portB,1
       rjmp main
select2: cbi portB,1
       sbi  portB,0
       rjmp main 

You can do this in several ways. The first step is make the code readable. Then you can see what you are doing.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David,

Why do you need the CPI after the ANDI? Surely the ANDI sets/clears Z anyway?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use the attiny24.
But thanks for the response I sure can go on with this help. I will try both ways and from now I will put comment behind it to make it more readable.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I use the attiny24.

Well good news - ALL the PORTA/PORTB registers are in the 0x00..0x1F range so all can be reached with SBI/CBI/SBIS/SBIC. I'd therefore suggest that when setting/clearing/testing single bits these would be the best opcodes for you to use and you can forget AND and OR bit masks. (but use those for multiple bit patterns). So to set 5 bits in DDRA use one IN/OR/OUT sequence rather than 5 SBIs.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What about:

sbis PINA,3
rjmp pin_a3_low

pin_a3_high:
;do something
rjmp exit

pin_a3_low:
;Do something else.
rjmp exit

exit:

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't need CPI. Nor do you need multiple tests or branches if you use EOR.

I think you can do the whole job in seven instructions. But this will not be so clear to the OP.

This is only nine.

Main:
;*** selection of the setting ***
       in   temp0,PINA
       ANDI temp0,$08    ; only look at bit #3
       breq select2      ; not set
select1: cbi portB,0
       sbi  portB,1
       rjmp main
select2: cbi portB,1
       sbi  portB,0
       rjmp main

This annoys me, there must be a more elegant way.

       cbi  PORTB,0
       cbi  PORTB,1
       sbic PINA,3    ; bit3 set
       sbi  PORTB,1   ; yes (select1)
       sbis PINA,3    ; bit3 NOT set
       sbi  PORTB,0   ; yes (select2)
       rjmp main

David.

Last Edited: Mon. Mar 29, 2010 - 02:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW if PA3 is a button the next thing you are probably going to want to consider is "bounce" - though if you just want the LED to light while the button is held this may not be an issue at first (the button will bounce and the LED will flicker but then it'll achieve a steady state)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

About that bouncing I will probably try that. But for now I want to learn how to read the individual pins

If I want every thing at once I will get lost in the code. So for now just pins and if I understand that I go further on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Make your life more comfortable and your code more readable:

; Aliases for every pin involved -
; NAME will be substituted by its literal DEFINITION from now on:
;
; DIRECTIVE      NAME    DEFINITION
;----------------------------------
#define          button  PINA,PA3
#define          out0    PORTB,PB0
#define          out1    PORTB,PB1
;----------------------------------

main:
        sbis    button          ; Is the button pressed (0)?
        rjmp    button_pressed  ; Yes, set outputs accordingly

button_released:                ; No - released (1), set outputs accordingly,
        sbi     out0            ;
        cbi     out1            ;
        rjmp    main            ; and continue polling the button.

button_pressed:                 ; Yes - pressed (0), set outputs accordingly,
        cbi     out0            ;
        sbi     out1            ;
        rjmp    main            ; and continue polling the button.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.