А у меня самый тонкий и короткий код.
CODE
/*! GPIO Mode Type */
typedef enum {
MD_IN, //!< Input *
MD_GO, //!< General purpose output
MD_AF, //!< Alternate function
MD_AN //!< Analog
} GPIO_MODE_t;
/*! GPIO Output Type */
typedef enum {
OT_PP, //!< Output push-pull*
OT_OD //!< Output open-drain
} GPIO_OTYPE_t;
/*! GPIO Output Speed Type */
typedef enum {
SP_LO, //!< 2 MHz Low speed *
SP_ME, //!< 10 MHz Medium speed
// 2 MHz
SP_HI = 3 //!< 50 MHz High speed
} GPIO_OSPEED_t;
/*! GPIO Pull-Up_Pull-Down Type */
typedef enum {
PL_NP, //!< No pull-up, pull-down *
PL_PU, //!< Pull-up
PL_PD //!< Pull-down
// Reserved
} GPIO_PUPD_t;
/*! GPIO Alternate Functions (4 bits)
The specific alternate function assignments for each pin are detailed in
the device datasheet */
typedef enum {
AF_00, //!< AF0 *
AF_01, //!< AF1
AF_02, //!< AF2
AF_03, //!< AF3
AF_04, //!< AF4
AF_05, //!< AF5
AF_06, //!< AF6
AF_07, //!< AF7
AF_08, //!< AF8
AF_09, //!< AF9
AF_10, //!< AF10
AF_11, //!< AF11
AF_12, //!< AF12
AF_13, //!< AF13
AF_14, //!< AF14
AF_15 //!< AF15
} GPIO_AFLH_t;
/*!****************************************************************************
@brief Port configuration
@details Конфигурация портов целиком
@param PORT - имя порта (A..G)
@param MDx, OTx, SPx, PLx, AFx - режимы x-битов порта
@note Default: MD_IN, OT_PP, SP_02, PL_NP, AF_00
*/
#define GPIO_CONF(PORT, \
MD00, OT00, SP00, PL00, AF00, \
MD01, OT01, SP01, PL01, AF01, \
MD02, OT02, SP02, PL02, AF02, \
MD03, OT03, SP03, PL03, AF03, \
MD04, OT04, SP04, PL04, AF04, \
MD05, OT05, SP05, PL05, AF05, \
MD06, OT06, SP06, PL06, AF06, \
MD07, OT07, SP07, PL07, AF07, \
MD08, OT08, SP08, PL08, AF08, \
MD09, OT09, SP09, PL09, AF09, \
MD10, OT10, SP10, PL10, AF10, \
MD11, OT11, SP11, PL11, AF11, \
MD12, OT12, SP12, PL12, AF12, \
MD13, OT13, SP13, PL13, AF13, \
MD14, OT14, SP14, PL14, AF14, \
MD15, OT15, SP15, PL15, AF15); \
GPIO##PORT->MODER = ( \
MD00 << 0 | MD01 << 2 | MD02 << 4 | MD03 << 6 | \
MD04 << 8 | MD05 << 10 | MD06 << 12 | MD07 << 14 | \
MD08 << 16 | MD09 << 18 | MD10 << 20 | MD11 << 22 | \
MD12 << 24 | MD13 << 26 | MD14 << 28 | (uint32_t)MD15 << 30); \
GPIO##PORT->OTYPER = ( \
OT00 << 0 | OT01 << 1 | OT02 << 2 | OT03 << 3 | \
OT04 << 4 | OT05 << 5 | OT06 << 6 | OT07 << 7 | \
OT08 << 8 | OT09 << 9 | OT10 << 10 | OT11 << 11 | \
OT12 << 12 | OT13 << 13 | OT14 << 14 | (uint32_t)OT15 << 15); \
GPIO##PORT->OSPEEDR = ( \
SP00 << 0 | SP01 << 2 | SP02 << 4 | SP03 << 6 | \
SP04 << 8 | SP05 << 10 | SP06 << 12 | SP07 << 14 | \
SP08 << 16 | SP09 << 18 | SP10 << 20 | SP11 << 22 | \
SP12 << 24 | SP13 << 26 | SP14 << 28 | (uint32_t)SP15 << 30); \
GPIO##PORT->PUPDR = ( \
PL00 << 0 | PL01 << 2 | PL02 << 4 | PL03 << 6 | \
PL04 << 8 | PL05 << 10 | PL06 << 12 | PL07 << 14 | \
PL08 << 16 | PL09 << 18 | PL10 << 20 | PL11 << 22 | \
PL12 << 24 | PL13 << 26 | PL14 << 28 | (uint32_t)PL15 << 30); \
GPIO##PORT->AFR[0] = ( \
AF00 << 0 | AF01 << 4 | AF02 << 8 | AF03 << 12 | \
AF04 << 16 | AF05 << 20 | AF06 << 24 | (uint32_t)AF07 << 28); \
GPIO##PORT->AFR[1] = ( \
AF08 << 0 | AF09 << 4 | AF10 << 8 | AF11 << 12 | \
AF12 << 16 | AF13 << 20 | AF14 << 24 | (uint32_t)AF15 << 28);
/*!****************************************************************************
@brief Port configuration lock
@details Зафиксировать конфигурацию портов
@param PORT - имя порта (A..G)
@param BITS - биты порта, которые нужно зафиксировать (0xffff - все)
@return
@note
*/
#define GPIO_LOCK(PORT, BITS); \
GPIO##PORT->LCKR = 0x00010000 | BITS; \
GPIO##PORT->LCKR = 0x00000000 | BITS; \
GPIO##PORT->LCKR = 0x00010000 | BITS; \
GPIO##PORT->LCKR;
Пример использования.
CODE
/*!****************************************************************************
@brief GPIO initialize
@note
*/
inline void GPIO_init(void)
{
GPIO_CONF(A,
MD_AN, OT_PP, SP_LO, PL_NP, AF_00, // 0: Wake-Up Button
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 1
MD_AN, OT_PP, SP_LO, PL_NP, AF_00, // 2: ADC1_IN3
MD_AF, OT_PP, SP_ME, PL_NP, AF_01, // 3: TIM2_CH4
MD_AN, OT_PP, SP_LO, PL_NP, AF_00, // 4: DAC1_OUT1
MD_AN, OT_PP, SP_LO, PL_NP, AF_00, // 5: DAC1_OUT2
MD_AN, OT_PP, SP_LO, PL_NP, AF_00, // 6: ADC2_IN3
MD_IN, OT_PP, SP_ME, PL_NP, AF_02, // 7:
MD_AF, OT_PP, SP_ME, PL_NP, AF_00, // 8: MCO
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 9
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 10
MD_AF, OT_PP, SP_HI, PL_NP, AF_14, // 11: USB_DM
MD_AF, OT_PP, SP_HI, PL_NP, AF_14, // 12: USB_DP
MD_AF, OT_PP, SP_ME, PL_NP, AF_00, // 13: SWDIO
MD_AF, OT_PP, SP_ME, PL_NP, AF_00, // 14: SWCLK
MD_IN, OT_PP, SP_LO, PL_NP, AF_00); // 15
// PB3 - SWO после сброса
GPIO_CONF(B,
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 0
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 1
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 2
MD_IN, OT_PP, SP_ME, PL_NP, AF_00, // 3: SWO
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 4
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 5
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 6:
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 7:
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 8
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 9
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 10
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 11
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 12
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 13
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 14
MD_AF, OT_PP, SP_ME, PL_NP, AF_01); // 15: TIM15_CH2
GPIO_CONF(C,
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 0
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 1
MD_AF, OT_PP, SP_HI, PL_NP, AF_03, // 2: COMP7_OUT
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 3
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 4
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 5
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 6
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 7
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 8
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 9
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 10
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 11
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 12
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 13
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 14
MD_IN, OT_PP, SP_LO, PL_NP, AF_00); // 15
GPIOE->ODR = 0x0000;
GPIO_CONF(E,
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 0
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 1
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 2
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 3
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 4
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 5
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 6
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 7
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 8: NW
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 9: NN
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 10: NE
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 11: EE
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 12: SE
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 13: SS
MD_GO, OT_PP, SP_ME, PL_NP, AF_00, // 14: SW
MD_GO, OT_PP, SP_ME, PL_NP, AF_00); // 15: WW
GPIO_CONF(F,
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 0
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 1
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 2
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 3
MD_AF, OT_PP, SP_HI, PL_NP, AF_02, // 4: COMP1_OUT
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 5
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 6
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 7
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 8
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 9
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 10
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 11
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 12
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 13
MD_IN, OT_PP, SP_LO, PL_NP, AF_00, // 14
MD_IN, OT_PP, SP_LO, PL_NP, AF_00); // 15
/* Заблокировать конфигурацию для всех битов портов */
GPIO_LOCK(A, 0xFFFF);
GPIO_LOCK(B, 0xFFFF);
GPIO_LOCK(C, 0xFFFF);
GPIO_LOCK(E, 0xFFFF);
GPIO_LOCK(F, 0xFFFF);
}