简体   繁体   中英

How to put a uint8_t in the middle of uint16_t without affecting other bits

I am writing a SPI driver for a DAC chip which uses 16bit SPI messages...the value that represents the output is from bit 11 to bit 4 (an 8 bit DAC). I have wrote this MASK but I have no idea how to achieve updating the data without affecting other bits:

#define MCP4901_SPI_MASK_DATA               0x0FF0
//So data mask in binary is 0000 1111 1111 0000

extern uint16_t mcpA;

static inline void mcpSetData(uint16_t* mcp, uint8_t value) {
    //????
   *mcp =| value & MCP4901_SPI_MASK_DATA; //NOT WORKING
}

You are correct about the use of the two operations | and & , but you are not using them in the right order, and you are not positioning one of the operands correctly.

Here is the correct way of doing it:

*mcp &= ~MCP4901_SPI_MASK_DATA; // Clear out the middle bits
*mcp |= ((uint16_t)value) << 4; // Put in the value in the middle

Since you are writing to a hardware register, a single write should be used to avoid possible side effects:

*mcp = (*mcp & ~MCP4901_SPI_MASK_DATA) | (((uint16_t)value) << 4);

MCP4901_SPI_MASK_DATA is inverted to clear out bits outside of 0x0FF0 . Alternatively, you could define the mask as 0xF00F , and drop the ~ operator.

The 8-bit value is shifted left by 4 to position it in the middle of 16 bits before "OR"-ing it into the number.

Demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM