久しぶりにSTM32F1で遊んでいます。
雛形を作りなおしているので、そのついでにGPIOを操作するマクロを作ってみました。
基本的にSTM32F1用。
マクロ
#ifndef __hardware_H
#define __hardware_H
#include "includes.h"
#define     HW(name, x, type)       name##_##x##_##type
#define     HW_OUT(name, x, val)    GPIO_WriteBit(HW(name, x, PORT), HW(name, x, PIN), (val) ? HW(name, x, ACTIVE) : !HW(name, x, ACTIVE))
#define     HW_IN(name, x)          (GPIO_ReadInputDataBit(HW(name, x, PORT), HW(name, x, PIN)) == HW(name, x, ACTIVE))
#define     HW_OT(name, x)          (GPIO_ReadOutputDataBit(HW(name, x, PORT), HW(name, x, PIN)) == HW(name, x, ACTIVE))
#define     HW_TGL(name, x)         HW_OUT(name, x, !HW_OT(name, x));
#define     LED_1_RCC       RCC_APB2Periph_GPIOD
#define     LED_1_PORT      GPIOD
#define     LED_1_PIN       GPIO_Pin_4
#define     LED_1_ACTIVE    0
#define     SW_1_RCC        RCC_APB2Periph_GPIOA
#define     SW_1_PORT       GPIOA
#define     SW_1_PIN        GPIO_Pin_0
#define     SW_1_ACTIVE     1
#endif /* __hardware_H */
LED1はアクティブLOW接続でResetで点灯、Setで消灯。
SW1はアクティブHIGH接続で押された時にSet。
使用例
void LED_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(HW(LED, 1, RCC), ENABLE);
    GPIO_InitStructure.GPIO_Pin = HW(LED, 1, PIN);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(HW(LED, 1, PORT), &GPIO_InitStructure);
}
void SW_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(HW(SW, 1, RCC), ENABLE);
    GPIO_InitStructure.GPIO_Pin = HW(SW, 1, PIN);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(HW(SW, 1, PORT), &GPIO_InitStructure);
}
スイッチを読む場合
if (HW_IN(SW, 1)) { ... } else { ... }
LEDを点灯させる場合
HW_OUT(LED, 1, 1);
LEDを消灯させる場合
HW_OUT(LED, 1, 0);
LEDを切り替える場合
HW_TGL(LED, 1);
もちろんスイッチやLED以外にも使用可能です。
ほとんど便利じゃないし、forで回したりできないので、ベタ書きとほとんど変わらないですが。
あとUnity(テストハーネス)使ってる人はわかると思いますが、マクロでごにょごにょやってるとエラった時にメッセージが非常に難解です。
今回はHWを接頭辞として使っていますが、LED(1, PORT)やSW(1, PIN)のほうが直感的な気がします。