assign char to bit

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

Can I assign a char value directly to a bit?

portD.4=0x5;

The overflowing bits would assign from portD.5, .6, .7, and .8

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

That particular notation cannot work in GCC. You'd need to add some more "meat" to the implementation to allow it to stand on its own in GCC.

For those compilers that do support such an extension, that notation (or a "meat-added" GCC implementation) would result in the least-significant bit of your byte (0x5 --> '1') being stored in the specified bit; all the rest of the byte would be discarded.

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

Okay, I'll byte. Why would you want to do this particular operation when there are other, clearer, techniques for setting bits?

Smiley

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

Those bits control a motor. The other 4 opposite bits on the port control a different motor.

I must change the first four or the last four ALL at one time, without affecting the opposite 4 bits.

Got any advice?

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

Easier method would be to create a temp char variable, and store the nibble of PORD which you don't want changed. Then change the other nibble to the new data and assign it to PORTD directly - voila, one nibble is changed at the same time with no intermediatry glitches, while the other nible stays constant.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

To set all 4 upper bits:

PORTD |= 0xf0;

To clear all 4 upper bits:

PORTD &= ~0xf0;

For both of these, any bit in the constant that is a 1, that bit in PORTD is affected. All other bits remain as they were.

Regards,
Steve A.

The Board helps those that help themselves.

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

I took the quote:

Quote:
I must change the first four or the last four ALL at one time, without affecting the opposite 4 bits.

To mean that the four bits (nibble) need to all be changed at once, with no intermediatry clearing of the nibble directly on the PORT (so correct data is always present with no cleared nibbles). In my example the code would be something like:

unsigned char TempPortD = PORTD;

TempPortD &= ~((CLEARUPPERNIBBLE)? 0xF0 : 0x0F);
TempPortD |= NEWMOTORDATA;

PORTD = TempPortD;

Of course, I may have misinterpreted.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I see your point, if some of the bits in the nibble need to be set and others cleared. However you don't need to create a separate variable. You could do something like this:

PORTD = (PORTD & 0x0F) | 0x50;

This sets the upper nibble to whatever value you want and keeps the old nibble value.

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
PORTD = (PORTD & 0x0F) | 0x50;
9e: 8b b1 in r24, 0x0b ; 11
a0: 8f 70 andi r24, 0x0F ; 15
a2: 80 65 ori r24, 0x50 ; 80
a4: 8b b9 out 0x0b, r24 ; 11

My apologies. I stupidly thought that the operations would be performed seperatly rather than all at once before being shifted back into the PORT register. Must be jetlag ;).

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

You are correct. Once I change the port to the new data, that will alter the motor leads; any clearing or changing will disrupt the flow.

I will test this operation; thanks for advice.
----------------------------------

Ok - lemme ask this; PORTD is a 8 bit address. Am I able to assign volatile CHAR variables directly the first and second 4-BIT memory addresses, - just as the PORTD variable has been asigned an integer 8-bit value to all 8 bits?

Example:

portDa would be CHAR first 4 bits, and portDb would be CHAR last 4 bits? Is that possible?

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

Do you mean you have something like:

unsigned char portDa = 0b1101;
unsigned char portDb = 0b0101;

(I'm assuming your C compiler can handle the 0b extension for binary numbers just so that what's going in the example is perhaps(?) a little more obvious). And do you mean that you want to then just say:

PORTD = (portDa << 4) | (portDb & 0x0f);

which would combine the two separate 4 bit "halves" into the entire 8 bit port - well that's fine.

BTW, the "& 0x0F" in there might not even be necessary if you know that portDb can't be assigned a value above 0x0F. In that case it's just:

PORTD = (portDa << 4) | portDb;

Cliff

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

clawson wrote:
Do you mean you have something like:

unsigned char portDa = 0b1101;
unsigned char portDb = 0b0101;

No.

I want PORTDa behave just as PORTD does, only it will point directly to the first four bits of PORTD, and PORTDb to point directly to the last four bits of PORTD.

When I assign data to PORTDa at runtime:

PORTDa = 0x5;
PORTDa = 0x8;
PORTDa = 0x0;

(same thing with PORTDb):

PORTDb = 0x3;
PORTDb = 0x2;
PORTDb = 0x7;

-They will only affect their respective 4-bit zone, within PORTD

Does that make sense?

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

I suppose that you could write macros to make your code read this way (or something similar). But I think that you are confused about memory addresses. PORTD is a single memory address, not 8. That memory address contains 8 bits. The AVR has opcodes that allow you to change one bit at a time, but if you want to write more than one bit simultaneously, then you must write all bits.

Regards,
Steve A.

The Board helps those that help themselves.