STM32でUSARTを使ってみる
出典: Wikimura
USART最初の一歩として、文字「a」だけをひたすら送り続けるプログラムを作りました。
目次 |
設定すべきこと
STM32-P103ボードでは、USART2にRS-232(メス)コネクタが付いています。 Olimex社の資料によるとSTM32-P103ボードは、下図のようにUSART2がDSub-9コネクタに接続されています。
この構成の基板でUSARTを使えるようにするには以下の設定が必要となります。
クロック有効化
「ペリフェラルの初期化と設定」 に書いたように、USARTに限らずペリフェラルを使用可能にするにはクロック有効化が必要となります。
STM32のブロックダイアグラムによると、このシリーズはAPBバス(ARM Peripheral Bus)を2つ持っていることがわかります。 USART2はAPB1に属し、GPIOAはAPB2に属しています。
この2つのペリフェラルを有効化するには、以下のようにします。
void RCC_Configuration(void)
{
// システムクロック設定
SystemInit();
// ペリフェラルクロック有効化
// USART2: APB1に属する。
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);
// USART用GPIO: APB2に属する。
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
}
初めにSystemInitを呼び出しています。 これはマイコンのセットアップ(特にPLL設定)のために、必須の設定らしいです。 これについては CMSISの説明に書かれていました。
RCC_APB1PeriphClockCmdとRCC_APB2PeriphClockCmdは似ていますが別物です。 USART2をAPB2で有効化しても動きませんので注意しましょう。
I/Oピン設定
STM32マイコンでは、GPIOピンのモードが以下のように切り替えられるようになっています。(リファレンスマニュアル7.1「GPIO functional description」参照)
- 入力
- Input floating
- Input pull-up
- Input-pull-down
- Analog Input
- 出力
- Output open-drain
- Output push-pull
- Alternate function push-pull
- Alternate function open-drain
GPIOのピンには、GPIOとしての機能と、割り当てられたペリフェラルとしての機能のどちらかを持たせることができるようです。(ペリフェラルが割り当てられていなくても、設定だけはできる?) ちなみに、未使用ピンは「Analog Input」モードにすると良いそうです。 下図にあるように、シュミットトリガつきの入力バッファをオフにすることで、immunity(電磁波耐性?)が高くなるそうです。サンプルプログラムのどこかに書いてあったのですが...
USART2を最小限の構成で使う場合、GPIOAのPin2をTx(送信)、Pin3をRx(受信)とします。
このとき、Txは「Alternate function push-pull」モード、Rxは「Input floating」モードに設定します。
なぜこのモードにするかがリファレンスに載っていないのですが...下図を見ればなんとなく分かりそうです。
この設定を行うために、以下の関数を作りました。
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// USART2 Tx (PA.02) を alternate function push-pull に設定
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // 設定対象
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // 速度(これは以降も使いまわす)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // モード
GPIO_Init(GPIOA, &GPIO_InitStructure); // 適用
// USART2 Rx (PA.03) を alternate input floating に設定
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
USART設定
USARTの速度やパリティなどの設定を行います。ここでは以下のように設定を行いました。 他にもオプションがあるので、用途に合わせて設定してください。
- ビット/秒: 9600
- データビット: 8
- パリティ: なし
- ストップビット: 1
- フロー制御: なし
これらを行い、USART2を有効化するために、以下の関数を作りました。
void USART2_Configuration( void)
{
USART_InitTypeDef USART_InitStructure;
// USARTパラメータ設定
// ボーレート: 9600 bps
// データビット: 8
// ストップビット: 1
// パリティ: 無し
// フロー制御: 無し
// 使用ピン: Tx, Rxのみ
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// USARTxに設定を反映
USART_Init(USART2, &USART_InitStructure);
// USART有効化
USART_Cmd( USART2, ENABLE);
}
プロジェクト
ここに「 プロジェクトを構成するファイル」を用意しました。 ファイルをEclipseプロジェクトディレクトリにコピーし、設定を正しく行えば、正しく動作するはずです。
プロジェクト設定
プロジェクトプロパティで以下の設定を行います。
ちなみに、Eclipseではカレントディレクトリのデフォルトは「実行ファイルの生成されるディレクトリ」です。 コマンドラインオプションでファイルを指定する場合、相対パスで各種ファイルを指定すると楽です。
カレントディレクトリはプロジェクト設定の「Environment」にあるCWDとPWDに書かれています。 これを変更することも可能ですが...とりあえずデフォルトのままが楽です。
また、下記のコマンドは全てパスが通っている状態で動きます。 システムでパスを通していない場合、プロジェクト設定の「Environment」に追加します。
- アセンブラ:
- コマンド: arm-none-eabi-as
- コンパイラ:
- コマンド: arm-none-eabi-gcc
- Cortex-M3必須1: -mcpu=cortex-m3
- Cortex-M3必須2: -mthumb
- 共通マクロ読込: -imacros ../macros.h
- リンカ:
- コマンド: arm-none-eabi-gcc
- 一般: -nostartfiles
- Xlinker系(スペースがあるとXlinkerを分けなくてはならないので、ひとまとめにした)
- リンカスクリプト指定: -script=../linker.x
- マップファイル出力: --primt-map>map.txt
- 出力設定
- ファイル名: out.elf
テスト
正しくビルドできれば後はテストするだけです。
まずOpenOCDを使うために外部ツールの設定を行います。これはすでにやっていれば飛ばしてOKです。 まだやっていなくても、一度設定すれば以降は使いまわせます。
それが終わったら、デバッガの設定を行います。 デバッグ方法は2通り用意します。新しく作ったプログラムを書き込んでから実行する「Flash書き込み付きデバッグ」と、普通のデバッグ用を用意します。
外部ツール設定
[Run]->[External Tools]->[External Tools Configuration...]で下図のように設定します。 なお、新しくプロジェクトを作る際は、プロジェクトディレクトリにOpenOCD設定ファイル(下図の場合はopenocd.cfg)を用意して下さい。
- Command
- OpenOCD実行ファイルのフルパス
- Arguments
- ${project_loc}/openocd.cfg (プロジェクトディレクトリ以下のopenocd.cfgを設定ファイルに指定)
こうすることで、${project_loc}の部分はプロジェクトディレクトリに置き換えられます。 プロジェクトごとにOpenOCD設定ファイルが必要になりますが、普通はプロジェクトごとにターゲットが異なるので、こちらの方が何かと都合が良いはずです。
デバッガ設定
[Run]->[Debug configurations...]メニューからデバッグ構成を作ります。 先に書いたように、Flash書き込みの有無で2種類の構成を作ります。。
Mainでは、デバッグ構成の対象プロジェクトと、実行ファイルを指定します。 それぞれで対象プロジェクトを設定しておけば、他のプロジェクトの操作中に対象外のデバッグ構成は選択できないようになります。
Debuggerでは、デバッガの実行ファイルを指定します。初期化シーケンスファイルの指定がありますが、ここではファイルを用意せず、次のCommandで初期化シーケンスを記述しました。
Commandでは、GDB初期化シーケンスを記述します。 GDB起動時に、どんなコマンドを送ってターゲットを初期化するかを指定します。
テスト
- USB-シリアル変換ケーブルをSTM32-P103ボードに接続(延長ケーブルがあるとつなげやすい)。
- USB-シリアル変換ケーブルのCOMポート番号を確認
- Windows標準のターミナルソフトウェア「ハイパーターミナル」を起動
- USB-シリアル変換ケーブルのポート番号を選択
- シリアル通信設定(USART2で設定した通りに)
- ビット/秒: 9600
- データビット: 8
- パリティ: なし
- ストップビット: 1
- フロー制御: なし
- [External Tools]からOpenOCDを起動
- [Run]->[Debug configurations...]から、Flash書き込み用構成を選択し[Debug]ボタンを押す
以上でターミナルに延々と「a」が表示されるようになります。

