йцyкeн прав - это не ради повышения уровня абстракции сделано. Но в
отличие от него я знаю зачем :). Во-первых, для контроля
устанавливаемых параметров: здесь все поля структуры имеют
свои/разные типы, а допустимые для них параметры определены через
enum, благодаря чему чужой параметр или произвольное число из
головы туда не подставишь. Но главное - второе, это особенность
архитектуры ARM, когда большинство периферийных регистров не имеют
жесткой специализации (как,
скажем, в AVR), а в них паровозиком понапиханы разные свойства. Из-за этого ручные операции с битами могут быть попросту опасными, т.к. ошибиться очень легко. Например, попробуйте подтянуть к питанию пины A4, A5, A7, A10, оперируя отдельными битами, - белый свет станет не мил :). А через структуру это выглядит совершенно примитивно:
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Сюда же добавляю, что этим методом обычно проводят лишь инициализацию, которая проводится обычно лишь однажды, а потому время исполнения функции HAL_XXXX_Init(&XXXX_InitStruct) обычно несущественно. Должно быть ясно, что таким способом ножками не дрыгают.