Reading from a single pin? (ATmega328P)

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

I am trying to build a simple switch LED circuit program using the assembly language without using SBI and SBIS.

 

L1:        LDI R20,0
        LDI R21,0
        SUB R20,R21    
        BREQ NEXT    
        RJMP L1
        
NEXT:    LDI R16,0x08
        OUT DDRB,R16
        OUT PORTB,R16
        RJMP L1

 

 

When the two numbers are equal the LED would light up. The problem is I do not know how to read from a pin. If I could get the input I can compare it with 0 as above(Correct me if I am wrong). Is it possible to read from a single pin using IN and ANDI command?

 

Thank you.

This topic has a solution.
Last Edited: Sun. Sep 15, 2019 - 02:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

You may find AVRbegginers.net helpful with assembly questions as they have many examples to learn from.
Good luck
Jim

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

Also, the AVR Instruction Set Manual:

 

http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf

 

edit

 

and the Tutorials forum here:

 

https://www.avrfreaks.net/forums/tutorials

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Sep 10, 2019 - 02:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You "read" a pin using the PIN register for the given port. That is, for the port controlled by PORTB, you read the state of that port's pins using PINB.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Note that the AVR is cleverly designed for things like this. The designers put things like PINB (the kind of register you would typically read to get inputs) in the very low IO space. They also added clever opcodes like SBIS and SBIC. So you can say things like:

wait_pin:
    SBIS PINB, 5
    rjmp wait_pin
...
; here when bit 5 of PINB becomes set

As it happens the AVR also has built in pull-up (bit not pull-down) resistors so it's very common to actually make inputs "active low". That is you configure a pin as input (0 bit in DDR) but you also turn on the pull-up (same bit to 1 in PORT) and then you have a switch on the pin that is normally open but that connects to ground (not Vcc) when closed. So you actually want to remain waiting while the pin is high then move on while it is low:

    CBI DDRB, 5; input
    SBI PORTB, 5; with pull-up turned on
    ...
wait_pin:
    SBIC PINB, 5
    rjmp wait_pin
...
; here when bit 5 of PINB becomes clear

 

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

Thank you very much for the reply sir.

 

I already made the circuit using SBIS,CBI and SBI. It was quite easy. I was wondering if it's possible in the way suggested in my original post. 

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

You know the solution already - why have you not tried it?

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

I assume this can be achieved by LDI and ANDI. If I could read the pin, I can compare it with 0. Is this right?

 

I am stuck on the stage where I have to read from a pin. Sorry if this sounds dumb :(

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

It's been years since i’ve done avr asm, so you’ll need to check my code, so here goes:
in r16,PINA
andi r16,(1<<PA1)
Then brne/breq ....
Pretty much as you said in your first post. You’d use this method mainly for multiple bits rather than only 1 bit - the AVR gods gave you fast single bit instructions.

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

Why would you use the inefficiency of IN, AND, BRxx when you can do it all in a single SBIS(/C) ? You paid for an AVR for a reason - it's because it is a great design of micro optimised for doing the typical kind of operations you want to do in an MCU like making conditional direction changes based on bit activity.

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

Thank you I'll try this :) 

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

Just to see If it's possible that way since I already made the program with SBIC command :( Sorry If I am pestering this forum with my ridiculously dumb questions.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well the way you test bits in any language is as old as the hills. You use the AND operation. In C if you have:

uint8_t val = 0xB7;

and you want to know is bit 5 is set you just use:

if (val & (1 << 5)) {
    
}

some people prefer to simply think if bit 5 in terms of:

if (val & 0x20) {
    
}

but whatever language it is the technique is the same - you use & (AND). This works because

B7 &
20

is:

10110111 & 
00100000

If you look vertically down that at each bit position then in bit 7 position you have 1 in the first number but 0 in the second number 1 & 0 is 0 which means the bit was not set. In the bit 5 position you have 1 in the first number and 1 in the second number 1 &  1 is 1. So the ultimate output of all that is:

10110111 & 
00100000
========
00100000

So the only 1 in the first number that "get through" is that one in the bit 5 position. All the other bits have been "masked" out. That is why a pattern like (1 << 5) or 0x20 (same thing) are usually called a "mask".

 

So it is with reading PINs. This could just as easily have been:

if (PINB & (1 << 5)) {
    
}

in this case it's whatever bit pattern is in PINB rather than "val" that is being tested. But all the same applies. There can only be two outcomes from this & operation. Either the bit 5 in PINB is set in which case the result is 0x20 or the bit is not set in which case the result is 0x0. In C anything that is not 0 is "true" so it enters the if() {} with 0x20 or anything else that is not 0x00.

 

So it is in Asm. 

  IN R24, PINB
  ANDI R24, 0x20
  BREQ dont_do_it

  ; stuff to run if bit is set (so AND result is Not Equal to 0)

dont_do_it:

If you wanted to test both bits 5 and/or 3 you could either do:

  ANDI R24, 0x21

or 

  ANDI R24, (1 << 5) | (1 << 3)

the state of the Z flag (to be used in BREQ or BRNE after this) would simply tell you if the result was 0x00 or not. The result will be non 0 if either 3 or 5 or both are set. So you might want to test the bits individually which you could do with SBRS such as:

SBRS R24, 5

which skips if bit 5 in the register read from the port is set. Or maybe:

SBRC R24, 3

which skips if bit 3 of the input value is 0.

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

clawson wrote:
They also added clever opcodes like SBIS and SBIC.

???  And you are congratulated for that "advice"?!?  Didn't we learn in the first post that

esavrperson wrote:
using the assembly language without using SBI and SBIS.

So then we need to go with the less-efficient memory-mapped location, and read it as if it were SRAM.  Hmmm; I guess that IN is not disqualified, so one can avoid SBIS and use SBRS with a mask instead?  So "never mind" I guess.

[edit] And then we learned that SBIC is OK, even though SBIS is not.  Must be broken.

[edit]  I've been commenting on that here since 2001:

https://www.avrfreaks.net/forum/...

lee wrote:

You people! Always want more, more, more. :)

Why, back when I was your age, I had to write whole databases using only 1's and 0's. And on bad days when the 1's were broken, only 0's were available!

 

and 2008

Why, back in the day we had to write databases with only ones and zeros. And there was hell to pay on the days that the zeros were broken.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Wed. Sep 11, 2019 - 08:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you looking for:  The AVR instruction set does not have a way to read single pins, other than the SBIS/SBIC instructions.  You have to read the whole port (using IN or some form of LD), and isolate the bit afterward.

 

(This is one of the things that makes abstracted pin IO, like Arduino's "digitalRead()", slower than it needs to be.)

 

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

theusch wrote:
And you are congratulated for that "advice"?!? 
Am I supposed to care, even in the remotest, what you think ? I don't get it.

Last Edited: Thu. Sep 12, 2019 - 08:40 AM