简体   繁体   中英

Can I add the bits of two ports to make a new bit sequence?

In my lab I'm supposed to test a 9 bit value but each port only contains 8 bits. According to the instructions, I use all bits on PORTD including PB0 to make this 9 bit value, but I have no plan on how I can do that and that's essentially the whole challenge of this problem. The rest of it should be easy, I only need to store a 9 bit value "borrowing" a bit from another port.

Microcontroller: ATmega1284

Problem: (Challenge): A car's passenger-seat weight sensor outputs a 9-bit value (ranging from 0 to 511) and connects to input PD7..PD0PB0 on the microcontroller. If the weight is equal to or above 70 pounds, the airbag should be enabled by setting PB1 to 1. If the weight is above 5 but below 70, the airbag should be disabled and an "Airbag disabled" icon should light by setting PB2 to 1. (Neither B1 nor B2 should be set if the weight is 5 or less, as there is no passenger).

Bits from separate registers can be combined in any way necessary using the bit-wise operators:

&  – Bitwise AND
|  – Bitwise OR
~  – Bitwise NOT
^  – Bitwise XOR
<< – Left Shift
>> – Right Shift  

The somewhat vague notation " PD7..PD0PB0 " suggests that PB0 is the LSB or the weight value. In that case, given:

PORTD DDDDDDDD
PORTB xxxxxxxB

then:

uint16_t weight = ((uint16_t)PORTD << 1u) | (PORTB & 0x01) ;

will result in a value for weight composed of bits:

0000000DDDDDDDDB

The sub-expression ((uint16_t)PORTD << 1u) shifts the value of PORTD left by 1 bit:

0000000DDDDDDDD0

(PORTB & 0x01) zeros all but bit-0, leaving bit-0 unchanged:

        0000000B

The two sub-expressions are then bit-wise OR'ed:

   0000000DDDDDDDD0
OR         0000000B
   ----------------
 = 0000000DDDDDDDDB

Note that it might be possible (safety considering) to simplify the task by using just the 8 bit value in PORTD and halving the limit values. Currently you have: "above 5 but below 70" , if you just read PORTD, the limits would be 3 >= PORTD < 35 . This may in fact be safer - when reading a single value from two separate registers you need to be certain the values you have are for the same sample, and that the value in the first register read did not change before you read the second. With only the one LSB in the PORTB register this will have little impact, but also makes it of limited value unless the data is somehow latched while it is read.

It depends on if PB0 is the MSB or LSB of register B. But what you cand do is using uint16_t variable and some masks to get the value you need. For example, you could do one of the following things.

PB0 is MSB

uint16_t sensor;
sensor = (PORTD << 1) | (PORTB >> 7);

PB0 is LSB

uint16_t sensor;
sensor = (PORTD << 1 ) | (PORTB & 0x01);

It can be done in many ways, and it is just one of them. In both solutions, all bits of register D are the most significant bits, and LSB, in the first one, would be the MSB of register B, and in the second one, would be the LSB of register B.

If you want your code is MISRA-C compliant you should initialize sensor variable.

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