How to set a bit in a register?

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

Is there a way to set a bit in a register without messing with the other bits? I believe the SBI and CBI instructions can do this but they don't work for registers above 0x1f.

What about the SBR instruction? I guess it's nothing special. Apparently it does the same thing as reading a register, oring in a bit, and writing it back, except it does it faster. Is that right?

In particular, the LCD control and status register A (LCDCRA) on the mega169 etc., has an interrupt pending bit that is set by hardware. That bit is cleared if a 1 is written to that position in the register. There are other bits in the register that must be set by software.

I guess the rule here is to read the register, "and off" the interrupt pending flag, "or in" the bit you want to set, and then write it back to the register.

Actually in this case I guess it doesn't matter what you do because when the LCD is enabled you get periodic interrupts come hell or high water. So if you miss one, there will soon be another.

Last Edited: Sun. Nov 4, 2007 - 02:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi :)

Yes of course :)

Example:

To set  bits:

REGISTER|=(1<<PINB1)|(1<<PINB2);

To clear  bits:

REGISTER&=~((1<<PINB1)|(1<<PINB2));

This is really easy:

Just take a bit of paper and see how these bits are moving ;)

Yours

Adam

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

lfryd, that works fine unless there are bits that can be set by the I/O hardware.

I believe what you are doing is reading the I/O register into a general purpose register, flipping some bits, and then writing the result back to the I/O register. But if the I/O hardware decides to change a bit after you have read the register but before you write it back, then you may overwrite that bit.

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

Helpful tutorial link:
https://www.avrfreaks.net/index.p...

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

Quote:
I believe the SBI and CBI instructions can do this but they don't work for registers above 0x1f.
This is for I/O locations (up to 0x1f as you know) not registers, SBR and CBR are for registers.

With CBI and SBI you can only work on 1 bit on an I/O location, with SBR and CBR you can work with multiple bits in a register, HOWEVER they only work with registers r16 to r31 as you are doing an immediate operation.

Are you working with assembler or C?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Quote:

Are you working with assembler or C?

I am working with C but I am not adverse to throwing in an assembler instruction if required.

Yes, I/O locations and registers drive me batty. Sometimes I wish I was still programming the Motorola HC11 :). Well to be honest these AVRs are more modern, flexible, powerful, smaller, efficient and cheaper than the HC11, so I shouldn't complain :)

Actually I haven't encountered any problems so far, and I don't expect to. Just wondering. The HC11 had instructions that could set a single bit and leave the others alone. Those instructions operated on any RAM or register address. It did make life simpler and I didn't have to worry about these things. :)

When I saw the SBR instruction I thought maybe this was the AVR instruction that could do it, but I guess not, and I guess such an instruction isn't needed. But I'm a worry wart :)

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

Quote:

Yes, I/O locations and registers drive me batty. Sometimes I wish I was still programming the Motorola HC11

??

OK, I'd have to dust off my Moto stuff. That chip family has no I/O setup registers for the peripheral subsystem optins like the AVR does? Then chalk one up for the AVR.

Or is your confusion related to the I/O addressing? If you don't care to use the smaller and faster and atomic instructions Atmel/AVR has provided for I/O work, then merely address them with the SRAM address--sure, slower and bigger and non-atomic but then you can be on a par with lesser architectures.

[From what I understand, this was a hurdle that ARM had to overcome when attacking the microcontroller arena. So now you see the AVR-attacking ARM models featuring their "fast I/O toggle rates". How do they do it? They have shadow registers for setting, clearing, configuring, etc. that add the I/O points, effectively, to another address space.]

Lee

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: Sun. Nov 4, 2007 - 05:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SBR/CBR on r16-r31 only, CBI/SBI on i/o 0-0x1F, so no, you can't touch individual bits above i/o 0x1F (although you have instructions that do it on sreg).

'generally' (assuming reg >i/o 0x1F)-
registers with just flag bits in them most likely need a 1 to clear a flag bit, so you don't read the register first, you just put the bitmask number into the register to clear the flag, and all other flags remain untouched- 'reg = (1<<AFLAG);'. Which is why you don't want to use 'reg |= (1<<AFLAG);', because then you will read any flags already set, and write them back, clearing the flag.

Registers that have more than just flag bits in them, you will have to mask off any flag bits you don't want cleared, or else you can end up clearing that flag- 'reg = (reg & ~(1<<AFLAG)) | (1<<ABIT);', which will leave AFLAG bit untouched.

Grab a copy of the AVR 8bit Instruction Set pdf from Atmel to see what the C compiler has to work with, or when you need to use asm in your app.

Anytime you are writing to flag registers, you just have to keep in mind what happens when doing read-modify-write.

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

Thanks curtvm. That's about what I figured.

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

theusch wrote:
From what I understand, this was a hurdle that ARM had to overcome when attacking the microcontroller arean.
Lee

ARM has a few more hurdles to overcome before I use another one. I tried an ARM7 and it must have been designed by Rube Goldberg. I'm sticking with the AVR now.

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

By the way, the SBR instruction is actually the same as ORI and the CBR instruction is the same as ANDI with the operand complemented. The assembler does the complementing so it looks like a separate instruction but it's not.

Another example is SER - set register, which is really the same as LDI 255. The translation is taken care of by the assembler.

If you look at the generated code you will see that they are the same.

Randy

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

Quote:
I am working with C
So, in theory, you should not worry about registers or I/O location as the C compiler does the work for you.
Quote:
Yes, I/O locations and registers drive me batty. Sometimes I wish I was still programming the Motorola HC11
register= A,B,D,X,Y (HC11)- I/O locations is SIMILAR to the stuff you have at $1000+ in the HC11 except that you MAY use different instructions for that like CBI,SBI,SBIS,SBIC etc. You can still use them as memory locations like the HC11 but you need to add $20 to their address to make them memory map accessible and use LDS ot STS. All of this is in case you want to get close and personal with the AVRs and use assembler.

You can think of registers r0-r15 as being like the memory in the Direct adress space of the HC11 ($00-$FF) just that you only have 16 locations. Registers r16-r23 are a bonus (can be used pretty much like A or B), r24 and r25 similar to the A or B register or D for some 16 bit ops, r26-r27=X, r28-r29=Y, r30-r31 bonus registers (can be used pretty much like A or B or as a pointer like X and Y)

I'm in the middle of porting some HC11 ASM code to the AVR for a client. It is such a nice, easy, relaxing task I feel ALMOST guilty charging for my time :lol:
I had forgotten about the nice thing like 16 bit IDIV or the 5x16bit counters, fortunately for this job I can get away with the 2*16 bit counters and can fudge some others with 8 bit counters and registers.

Separate I/O space is not just confined to AVRs, most other micros have the same setup, even the good ol' Z80. You must have lived a sheltered Micro life :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Quote:
I am working with C
So, in theory, you should not worry about registers or I/O location as the C compiler does the work for you.

Exactly. The joy of C is that you just use the construct that Ilfryd showed above or in the linked 101 bit tutorial and the C compiler will use SBI/CBI if it can see that only one bit will be changing state and the destination IO is 0x00..0x1F, otherwise for that range it will generate in/or/out or in/and/out. It will geenrate the same sequence for any bit manipulation 0x20..0x3F and for IO above that it will generate lds/or/sts or lds/and/sts. This is one of the joys of C - you the programmer don't need to worry about what opcode sequence the compiler is generating - it all happens behind your back and you can be sure the best sequence possible will be used. The one rider to that is the point that Steve made - sbi and cbi are atomic but in/op/out or lds/op/sts are not atomic and the sequence might be interrupted.

Cliff

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

js wrote:
You must have lived a sheltered Micro life :)

Yep. A Motorola life. :)

It was a sad day when the Motorola CPUs were replaced by Intels. I haven't been the same since. :)

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

Quote:
It was a sad day when the Motorola CPUs were replaced by Intels.
It was a sad day when Motorola was taken over and run by idiots!....here I go again, from a Motorola lover to a Motorola hater... :evil:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly