开发者

Storing a 4-bit value in the middle of an 8-bit register

开发者 https://www.devze.com 2022-12-17 04:12 出处:网络
I need to count from 0 to 10 and store those values in binary format in ADCON0(5:2). How do I point at bit 5 of this register? Bit 5 is named ADCON0bits.CHS3. If I store a 4 bit variable to ADCON0bits

I need to count from 0 to 10 and store those values in binary format in ADCON0(5:2). How do I point at bit 5 of this register? Bit 5 is named ADCON0bits.CHS3. If I store a 4 bit variable to ADCON0bits.CHS3, will bits 1 - 3 be written to bits 4 - 2 of the register?

Also, are there any 4 bit data types that I could use?

This is all on a PIC microcontroller.

Edit: I need to store 4 bits in the register like s开发者_Python百科o:

unsigned char count = 10 //max value
[X][X][1][0][1][0][X][X]

This is in line with what was assumed below, but I figured I would clear up my question a bit.


When you say you are writing bits 1-3 of your count into positions 4-2 of your register, do you explicitly mean you are reversing the order of the bits? In this answer I will presume that that was not what you meant.

You can express a bit field explicitly as a struct. Presuming that you are dealing with a 16 bit register, your struct could look something like this:

struct adcon {
    unsigned char someflag    : 2;
    unsigned char count       : 4;
    unsigned char other_bits  : 2;
}; 
With each struct member, you specify the number of bits. Then you can operate on the appropriate bits in the register by casting the register to the struct type, and operating on the members of the struct.

(adcon) ADCON0.count = count;

Edit: fixed up the code based on feedback, thanks.


Writing to a bit variable stores the truth value of that variable to the bit. For example, writing:

ADCON0bits.CHS3 = 3;

will set that bit to 1.

If bit5 refers to the bit masked by 0x20 (00100000) and you need to store the 4 bit number in bits masked 0x3c (00111100) then you can use bit shifts and bitwise operations:

// First clear bits 1-5:
ADCON0 &= ~0x3c;

// Now set the bits to correct value:
ADCON0 |= (count << 2); // <-- remember to shift 2 bits to the left

update: As mentioned by Ian in the comments. This sets ADCON0 to an intermediate value before updating. In this case it is OK since it is only selecting the A/D channel and not actually executing the conversion. But in general it's better to do:

unsigned char temp_adcon;

temp_adcon = ADCON0 & ~0x3c;
ADCON0 = temp_adcon | (count << 2);


See the answers for this SO question.

Note that you are doing a read-modify-write operation. You have to be careful of race conditions when doing this. Race conditions may be caused by:

  • The hardware itself changing bits in the register (e.g. A/D converter operation completes and sets flags). The design of the hardware should provide a means for you to avoid this problem—there are several possible solutions—read the manual for the micro/peripheral to find out.
  • Your own interrupt routine(s) also writing to the register. If so, when your main (non-interrupt) code writes to the register, it should be done within an "interrupts disabled" context.


I'm not sure about the exact register ADCON0, but often you can read the register, mask the 4 bits and insert your count and then use that value to write back to the register.

Just in case, masking is performed with an AND operation and inserting is an OR operation with the count shift over 2 bits in your case.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号