Например, для удобного обеспечения модульности программы ещё при написании отдельных модулей. Ввод/вывод можно прятать. Трассировку бывает удобно делать. Практически компиляторами обращение к функции не выбрасывается (инлайниться может). Ещё при клонировании модулей помогает. При портировании тоже удобнее.
В хедерах для STM32, как впрочем и для других Cortex-M, прослеживается:) поддержка CMSIS - обращение к периферии по указателю на структуру - такое удобно записывать именно подготовкой структуры и копированием её, а не копированием поэлементно. И тут без обёртки часто невкусно. Возъмём яркий пример - UART. Тот же бодрейт рассчитать нужно, получив текущее значение клока (обычно есть такая функция в комплекте, а руками - либо писать ровно то же, либо костылить мэджики), да ещё по какой-нить несложной формуле, которая давно переписана из DS, ну и выбрать всякие четности и прочая - где битами, а где кодом. Пишется обертка, которой передаётся набор параметров в нормальном "человеческом" виде (в венде обертки работают с DCB, тут какая-то другая структура) и она уже считает и пишет тот же бодрейт в смещение BDRT или BAUD (я эти названия регистров и запоминать не хочу - есть чем другим заняться) структуры, соответствующей кремнию, ну и остальные параметры так же. У LPC одни названия этих полей, в своих регистрах, у STM32 - свои, у EFM32 - свои. Мне не нужно их помнить - я понимаю, что за регистр/поле мне нужны при отладке - залез в доку и получил имена/явки/пароли, но это не "изучать", а использовать, и потому я спокойно воспользуюсь функцией из либы, если она позволяет мне выполнить настройку с понятными именами параметров, проверю в отладчике, если нужно, но не буду заниматься переписыванием функции инициализации только из-за того, что вдруг научился запоминать имена регистров. И я конечно же прочитал, какой там USART, обратил внимание на нюансы, и посмотрел на код инициализации - обеспечивает ли он нужное решение.
Извиняюсь, если несколько сумбурно.