Difference between OUT and SBI

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

I'm just beginning to learn assembly and I'm curious what the difference between the 'out' and 'sbi' instructions are.

The data sheet specifies that out "stores data from register Rr in the Register File to I/O Space"

and sbi "Sets a specified bit in an I/O register"

I see the differences but I don't really understand them.

It looks like out will set the bits from a register and sbi sets the bits from the supplied constant value. Is that the only difference or am I way off here?

Thanks :D

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

'out' changes all bits, 'sbi' and 'cbi' - just one.

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

BINGO!!

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Ahhh! Ok... well that kinda makes sense

So, forgive the newb question here but how do I know what bit it's setting? If I understand correctly any 1 register is going to contain 8 bits,.. now I'm a little confused.

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

look at the instruction, there are 2 parameters, first is the I/O address...the 2nd is the bit number.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

glitch wrote:
look at the instruction, there are 2 parameters, first is the I/O address...the 2nd is the bit number.

Doh - I get it.. I was still thinking in terms of passing a byte. Thanks guys!

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

Oh for the love and honour of God - I went to some length to explain this to you yesterday:

https://www.avrfreaks.net/index.p...

Presumably that was a complete waste of my time?

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

clawson wrote:
Presumably that was a complete waste of my time?

Not completely. I learnt a thing or two :) Thanks!

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

clawson wrote:
Oh for the love and honour of God - I went to some length to explain this to you yesterday:

https://www.avrfreaks.net/index.p...

Presumably that was a complete waste of my time?

I'm still learning! For some reason after I read about "out" I got the two mixed up.. I really do appreciate your post though - it was a great help. Thanks again :D

Which brings me to this:

#include 

.global main


main:
        ldi     r16, 0xFF 
        out     DDRD, r16 

        sbi     PORTD, 0

I'm just trying to turn an LED on... but I'm getting

led.S:10: Error: number must be less than 32

For the sbi instruction... where am I going wrong here?

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

you need to look at the register list for the AVR you are using. Only the I/O ports that are located in the first 32 locations (I/O address 0x00-0x1f) are accessible via SBI/CBI.

You'll have to use IN/OUT for anything between 0x1f and 0x3f (IN/OUT also works on 0x00-0x1f)

If the AVR you have has extended I/O, These ports will start at a memory address of 0x60 and above. These I/O ports are only accessible via STS/LDS (or other memory access functions) IN/OUT and the other direct I/O instructions will not work on these I/O Ports.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Ahhh ok... that makes sense.

Here's what I've got now:

#include 

.global main                        ; define main as a global


main:
        ldi     r16, 0xFF 
        out     DDRD, r16 

        in      r17, PD0
        out     PORTD, r17

Does everything look ok here? Unfortunately, I'm still not having any luck (this is a 2313).

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

No.
Use this, if you want to set PD0 bit, keeping/setting other PORTD bits to 0:

ldi r17, 1<<PD0
out PORTD, r17

Or this, if you want to set PD0 and keep other bits in state they were before:

in r17, PORTD
ori r17, 1<<PD0
out PORTD, r17
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lads, I'm afraid SFR access in avr-as is not quite as simple as you seem to be attempting above. This all comes down to the 0x20 offset thing I talked about in the thread linked above. The .h files for the various AVR chips are optimised for use by the C compiler which means that if you wander into the murky world of assembler you need to use some special macros to "fix up" the SFR addresses with the right offset values. In particular _SFR_IO_ADDR(). No doubt you already read the following page in the manual but, if you didn't, you should study it in depth:

http://www.nongnu.org/avr-libc/u...

also see this page in the manual:

http://www.nongnu.org/avr-libc/u...

and in particular take a look at isrs.S as another example of avr-as code.

Cliff

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

Thanks Cliff, once again you've been a great help.