020 LEDチカチカのソースを解読する
上のほうにある「040 eclipse本家のサイトのダウンロードファイルでSTM32開発環境を作ってみました」ではサンプルプログラムとしてLEDチカチカさせるソースコードを動かしています.このソースコードを解析することで、どんな風にプログラムするのかを理解しようと思います.
#include "stm32f10x.h" CPUのハードウエアによって決まる割り込み番号やレジスタアドレスを定義しています
#include "platform_config.h" STM32-DISCOVERY value lineのプリント基板仕様の定義をしています
uint32_t Count;
void GPIO_Configuration(void);
void Delay(__IO uint32_t nCount);
int main(void)
{
BoardInit(); リセットとclockの初期設定をします
GPIO_Configuration(); GPIOの初期設定、下記にコードがあります
while (1) LED点滅ループ
{
プリント基板のSWをチェックして、点滅周期を変える.
OB_SW_IS_PRESSEDは、STM32_VLD.hで定義されています.
if (OB_SW_IS_PRESSED) Count = 0xFFFFF;
else Count = 0x1FFFF;
LEDのGPIOを1にする.OB_LED_PORT, OB_LED_PINはSTM32_VLD.hで定義されています.
GPIO_SetBits(OB_LED_PORT, OB_LED_PIN);
遅延時間.コードは一番下にあります.
Delay(Count);
GPIO_ResetBits(OB_LED_PORT, OB_LED_PIN);
Delay(Count);
}
}
void GPIO_Configuration(void)
{
//Supply APB2 Clock
RCC_APB2PeriphClockCmd(OB_LED_GPIO_RCC | OB_SW_GPIO_RCC , ENABLE);
↑これはSTMのライブラリ関数です.stm32f10x_stdperiph_lib_um.chm がSTMライブラリの説明書です.
RCCとはresetとclockのことでして、APB2バスにぶら下がったperipheralのclockをenableするのがこの関数の仕事です.
下図を見るとAPB2バスにぶら下がったperipheralが何であるかがわかります.
OB_LED_GPIO_RCC と OB_SW_GPIO_RCC はSTM32_VLD.hで次のように定義されています.
#define OB_SW_GPIO_RCC RCC_APB2Periph_GPIOA
#define OB_LED_GPIO_RCC RCC_APB2Periph_GPIOC
ゆえに、LEDが接続されたGPIOCと、SWが接続されたGPIOAをenableにしています.
stm32f10x_stdperiph_lib_um.chm を読むと、RCC_APB2PeriphClockCmd()の引数は、次が可能です.
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, RCC_APB2Periph_ADC1, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3, RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17
↓GPIOを利用するために構造体をつかうようです.
GPIO_InitTypeDef GPIO_InitStructure;
stm32f10x_stdperiph_lib_um.chm を読むと構造体の説明があります.
typedef struct {
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
構造体のメンバーにはこんな選択肢があります.
GPIO_Pin STM32のGPIOは16bitなのかといまさら気付いたわたくし
#define GPIO_Pin_0 ((uint16_t)0x0001)
#define GPIO_Pin_1 ((uint16_t)0x0002)
#define GPIO_Pin_2 ((uint16_t)0x0004)
#define GPIO_Pin_3 ((uint16_t)0x0008)
#define GPIO_Pin_4 ((uint16_t)0x0010)
#define GPIO_Pin_5 ((uint16_t)0x0020)
#define GPIO_Pin_6 ((uint16_t)0x0040)
#define GPIO_Pin_7 ((uint16_t)0x0080)
#define GPIO_Pin_8 ((uint16_t)0x0100)
#define GPIO_Pin_9 ((uint16_t)0x0200)
#define GPIO_Pin_10 ((uint16_t)0x0400)
#define GPIO_Pin_11 ((uint16_t)0x0800)
#define GPIO_Pin_12 ((uint16_t)0x1000)
#define GPIO_Pin_13 ((uint16_t)0x2000)
#define GPIO_Pin_14 ((uint16_t)0x4000)
#define GPIO_Pin_15 ((uint16_t)0x8000)
#define GPIO_Pin_All ((uint16_t)0xFFFF)
#define IS_GET_GPIO_PIN(PIN)
#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))
GPIO_Speed これはゲートドライブ能力というかスルーレートですね
GPIO_Speed_2MHz
GPIO_Speed_10MHz
GPIO_Speed_50MHz
GPIO_Mode これは重要ですね
GPIO_Mode_AIN Analog Input
GPIO_Mode_IN_FLOATING Input Floating
GPIO_Mode_IPD Input Pull-down
GPIO_Mode_IPU Input Pull-up
GPIO_Mode_Out_OD Output Open-Drain
GPIO_Mode_Out_PP Output Push-Pull
GPIO_Mode_AF_OD Alternate Function Open-Drain
GPIO_Mode_AF_PP Alternate Function Push-Pull
↓そんなわけで、LEDのポートを具体的に設定しています.
/* Configure OB_LED: output push-pull */
GPIO_InitStructure.GPIO_Pin = OB_LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
OB_LED_PINは、STM32_VLD.hで別途定義されたパラメータです.
#define OB_LED_PIN GPIO_Pin_9
GPIO_Mode_Out_PPとGPIO_Speed_50MHzは構造体のメンバーの選択肢として上で説明した中にありますので、とくに疑問はありません.
↓構造体をセットした後で、GPIOを初期設定します.
GPIO_Init(OB_LED_PORT, &GPIO_InitStructure);
GPIO_Init()の呼び方は、GPIOxとさっきの構造体を引数にするらしいです.
第一引数の選択肢は、GPIOA~GPIOGです.
OB_LED_PORTは、STM32_VLD.hでGPIOCと別途定義されています.
#define OB_LED_PORT GPIOC
↓つぎはSWの具体的な設定です.
/* Configure OB_SW: input floating */
GPIO_InitStructure.GPIO_Pin = OB_SW_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
OB_SW_PINは、STM32_VLD.hで別途定義されています.
#define OB_SW_PIN GPIO_Pin_0
GPIO_Mode_IN_FLOATINGは構造体のメンバーの選択肢として上で説明した中にありますので、とくに疑問はありません.
↓GPIO初期化関数をコールします.
GPIO_Init(OB_SW_PORT, &GPIO_InitStructure);
OB_SW_PORTは、STM32_VLD.hで別途定義されています.
#define OB_SW_PORT GPIOA
}
遅延時間.ただのloopで時間を決めているだけですので、タイマーは使っていません.
void Delay(__IO uint32_t nCount){ for(; nCount != 0; nCount--); }