Инициалиация в одном месте хорошо. Но иногда не прокатывает: при работе с встраиваемыми модулями (GSM и прочие) сразу инициализировать ноги нельзя, вначале надо подать на модуль питание. И, соотвественно, иницалиировать в третье состяоние при снятии питания.
Таким образом, инциализация ног происходит не разово, а постоянно в работе.
Для LPC и STM создан "drv_gpio"
Все регистры для установки ног вычиляются внутри функции IO_SetupPin(..)
С одной стороны, лишние накладные расходы, с другой - код намного читабельнее и понятнее.
Единстенное, что никак не стандартизируешь - вариант альтернативной конфиграции ноги. Тут уж придется лезть в даташит.
CODE
#ifndef __DRV_IOPORTS_H
#define __DRV_IOPORTS_H
enum __pindirection {
PIN_IN,
PIN_OUT,
PIN_ALTOUT
};
enum __pullupmode {
ppullINACTIVE = 0,
ppullDOWN,
ppullUP,
ppullREPEATER
};
enum __pinslew {
pslewENABLED = 0,
pslewDISABLED = 1
};
enum __pinmode {
pinNORMAL = 0,
pinOPENDRAIN = 1,
pinANALOG = 2,
};
enum __pinfilter {
pglfENABLED = 0,
pglfDISABLED = 1
};
enum __pinntest_res {
PIN_OK,
PIN_SHORTLOW,
PIN_SHORTHIGH
};
#define pmANALOG 0
#define pmDIGITAL 1
#define PORTA A
#define PORTB B
#define PORTC C
#define PORTD D
#define PORTE E
#define PORTF F
#define PORTABASE ((void*)&GPIOA_CRL)
#define PORTBBASE ((void*)&GPIOB_CRL)
#define PORTCBASE ((void*)&GPIOC_CRL)
#define PORTDBASE ((void*)&GPIOD_CRL)
#define PORTEBASE ((void*)&GPIOE_CRL)
#define _PORTBASE(port) ((void*)&(GPIO ## port ## _CRL))
#define _PORTSET(port) GPIO ## port ## _BSRR
#define _PORTCLR(port) GPIO ## port ## _BRR
#define _PORTPIN(port) GPIO ## port ## _IDR
#define PORTSET(port) _PORTSET(port)
#define PORTCLR(port) _PORTCLR(port)
#define PORTPIN(port) _PORTPIN(port)
#define PINSET(port, pin) _PORTSET(port) = BIT(pin)
#define PINCLR(port, pin) _PORTCLR(port) = BIT(pin)
#define PINREAD(port, pin) (!!(_PORTPIN(port) & BIT(pin)))
#define PINSETUP(port, pin, dir, pu, pm, s, f) \
IO_SetupPin(_PORTBASE(port), pin, dir, pu, pm, s, f)
#define PINMODE(port, pin, mode)
#define PINDIR(dir, port, pin) IO_PinDir(dir, port, (1UL << pin))
#ifdef __cplusplus
extern "C" {
#endif
void IO_Init(void);
void IO_SetupPin(void * portbase,
int pin,
enum __pindirection dir,
enum __pullupmode pumode,
enum __pinmode pinmode,
enum __pinslew slewrate,
enum __pinfilter filter);
enum __pinntest_res
IO_PinTest(int port, int pin);
void IO_PinDir(enum __pindirection dir, int port, unsigned long pinmask);
#ifdef __cplusplus
}
#endif
#endif //__DRV_IOPORTS_H