久しぶりに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)のほうが直感的な気がします。