What you described first is what is called I/O port addressing, popularized by Intel. Intel microprocessors have I/O addresses separate from memory addresses, e.g. you can have I/O port 45, and also memory address 45, and there is no conflict. Whereas Motorola-style microprocessors use the same address space for both memory and I/O, so address 45 has to be one or the other. Which one depends on the design of the system. This distinction (Intel vs Motorola-style addressing) goes back 40 years.
So yes, the I/O address would be put on the address bus. In the Intel 8080 for example, which had a 16-bit address bus, the I/O address would be put only on the lower byte of the address bus since there was a maximum of 256 I/O port. In addition, a line would be asserted indicating the address on the bus is for I/O and not memory.
Meanwhile, as you said, all hardware controllers are listening to the bus. Another term used for controller is peripheral. When the address on the bus matches the address of the peripheral, then data is either passed from the microprocessor's data bus to the peripheral (writing), or from the peripheral to the microprocessor (reading), depending on additional lines which indicate whether data is being written to or read from the peripheral.
I have been using the term microprocessor, instead of microcontroller, because microcontrollers in general do not have external address and data busses, so your first example wouldn't make any sense with microcontrollers.
A "hardware controller" is not the same thing as microprocessor or microcontroller, rather it could be a peripheral card in your PC. What's a little confusing, in the case of a peripheral card there is almost certainly a microcontroller on the hardware controller or peripheral, but that microcontroller is just part of the peripheral, and you cannot equate hardware controller = microcontroller.
In any case, what you are referring to as a "controller" is a piece of hardware. However, it may not be a separate piece of hardware like the peripheral cards I have been referring to. Instead, it might simply be a separate chip on the motherboard.
Modern PC's typically have two I/O chips, one called the Northbridge and the other the Southbridge. The Northbridge usually has a memory controller and video controller. The Southbridge handles interfaces such as USB, audio, serial, ISA bus, interrupt controller and the IDE channels.
And finally, the controller may be integrated right into the microprocessor or microcontroller itself; that's always the case for microcontrollers since their I/O is part of the chip and they generally have no external address or data busses. So instead of putting I/O addresses on an external address bus, the processor would just write and read directly to/from registers within the chip.
If you are writing a standalone program (no OS like Windows) for a microprocessor or microcontroller, you don't have to have software drivers to talk to it, rather you can write directly to the hardware yourself if you want to. But these controllers are often pretty complicated to understand at the hardware level, and so it is much easier to use a library provided by the chip manufacturer. (And if there isn't one, programmers often make their own and use them from one project to the next, or even share them on a GitHub.)
In the PC, using a operating system like Windows or Linux, regular programs are not allowed to talk directly to the hardware (if they try, it causes the program to be terminated). This is enforced because if a program could muck around directly with the hardware, it would be too easy to take the entire system down.
Rather there are software device drivers that have a set of standard interfaces for each type of peripheral. This isolates the hardware details of how to talk to the peripheral, and instead presents a higher-level I/O interface to the programs running on the PC to talk to it.
Device drivers can even make one piece of hardware look like another. All PC's used to have hardware RS-232 communication ports. Now they seldom do. Instead, if one really needs to have a hardware RS-232 interface, they can purchase a USB to RS232 serial adapter. When this is plugged into a PC, it's driver creates a "virtual" COM port in the device manager list, and a user programmer cannot tell the difference between this and a real COM port on the back of the PC.