Alternative ways of access. Really, really handy. For example, sometimes you want to access a memory location as a 32-bit operation, sometimes you want to assign or read part of it as a, say, 8-bit signed integer, or even more fancier, a 5-bit signed integer. Doing that using unions and bitfields results in more readable and less error prone code compared to a massive hack of bit masking and shifting.
Sometimes different parts of documentation group configuration register bits differently. For example, STM32 SPI has a 16-bit transfer size register as an upper half of a control register. You may want to use the control register under the name given on the datasheet, but you may also want to access SPI->TSIZE = 42; for convenience and clarity.
Another good example would be reading 57 bytes of calibration data out of a device: you just want to access them as calib.u8[idx] or calib.u32[idx] depending on the communication data width available; but after the readout, you want to access it using calib.voltage_offset or whatever.
Anonymous structs inside union are great because you don't need to access thing.done_one_way.blargh and thing.done_another_way.blorgh, just using thing.blargh and thing.blorgh is enough.
Initializers get a bit tricky, though, you need quite some extra {{{}}}.
Do note that with bitfields, you rely on particular compiler putting them in particular order, possibly with no proper attributes to control the order available. Further limiting yourself to not using bitfields allows almost portable solution given that any decent compiler have had the concept of packed struct for a long time. The syntax for giving that attribute varies compiler to compiler, but you can #define that out for simple porting.
A pedantic note is worth mentioning: C standard at least originally - I haven't looked if this has been fixed - said that union cannot be used for such purpose; by writing one element in the union, you are supposed to only read the same element back, not access the same data through the another element; only rendering the union useful for memory saving of static objects, pretty useless. In practice, this is meaningless; everybody uses unions in the "forbidden" way because that's actually very useful, and any decent compiler works correctly (if it doesn't, and if it's being maintained, it will get fixed due to widespread usage of union).
As a general note, sometimes on microcontrollers, the actual memory access instruction width matters. You may really NEED to read or write a 8-bit AHB/APB bus operation, instead of writing the full 32-bit register, or even worse, read-modify-write.