STM32でUARTをやってみる6(float型printfをUART経由で出力)

何だかんだこのシリーズも6個目ですねw

前回まででUARTの基本的な使い方はマスターしたと思います。
今回はCubeMXでの出力は詳しくは解説しないので

まだの方は1から読んでみてください

gsmcustomeffects.hatenablog.com

gsmcustomeffects.hatenablog.com

gsmcustomeffects.hatenablog.com

gsmcustomeffects.hatenablog.com

gsmcustomeffects.hatenablog.com

さっそくやってく

今回の環境は以下に示す通り

  • AC6 SystemWorkbenchForSTM32
  • STM32F303K Nucleo
  • Teraterm

とりあえずCubeでUART2を有効にしてボーレートを各自設定しファイルを出力する。
ココまでは今までと同じです。

Syscall.cを持ってくる

syscall.cがCにおけるスタンダードライブラリを読んでいるのでそれをどっかからもってこないとリンクできないわけです。
とりあえずSTが提供するサンプルには入っているのですがCubeMXが出力するsrcフォルダには入っていません。

なのでAc6で適当な空プロジェクトを作る必要があります。
めんどかったらSTが提供するサンプルから引っ張ってくるという方法もあります。

f:id:gsmcustomeffects:20170404195559p:plain

で今回使うボードを選択

f:id:gsmcustomeffects:20170404195630p:plain

CubeHALを選択

f:id:gsmcustomeffects:20170404195658p:plain

そうするとsyscall.cができるのでそれをCubeMXが出力したSrcにコピーしてくる

f:id:gsmcustomeffects:20170404195814p:plain

f:id:gsmcustomeffects:20170404195841p:plain

んで一度コンパイルします。


Main.cでputcharを再定義。

syscall.c内では

__io_putchar(int ch) __attribute__((weak))

のようにWEAK定義されているのでMain内で再定義してこっちを使うよということをコンパイラに教えてあげる作業をします

こういうふうにします。

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
void __io_putchar(uint8_t ch) {
HAL_UART_Transmit(&huart2, &ch, 1, 1);
}

printfというのは内部で書式を整えてputcharを呼び出しているのでそのputcharの内部をHALの一文字送信APIに置き換えるということです。

コンパイルマクロがGNUとかついてるのはARMの純正コンパイラではfputcと定義されてるのでコンパイラごとに読み替えが効くようにしているためです。

次にprintfを呼ぶ前にどこか最初以下の行を挿入します

setbuf(stdout, NULL);

これはprintfの仕様みたいで1024byte入れた後に呼ばれるのでコレがないと変なハンドラに飛びます。
とりあえずバッファをフラッシュするといいみたいです。

ここまででとりあえずint型のprintfは動きます。

だいたい15KBぐらいになります。

Linkerフラグの編集

リンカーオプションにfloatを追加して再ビルドする必要があります。

やることとしてはlinkerのフラグ部分に-u _printf_floatというのを追加するだけです。

f:id:gsmcustomeffects:20170404201644p:plain

それであとはApplyして再ビルドします。

f:id:gsmcustomeffects:20170404202009p:plain

結構サイズがでかくなります。

いうてGCCならKEILと違って32KB以上もビルドできるしFloat扱うようなマイコンはフラッシュ自体大きい物がのってるので特に悩まないかと思います。

動作のようす

こんな感じに書いて

f:id:gsmcustomeffects:20170404202315p:plain

Teratermで表示する

f:id:gsmcustomeffects:20170404202339p:plain

ちなみに桁数ちゃんと合わせないとゴミが入りますw

ちなみにSemihostingというARMの機能を使ってSWD経由でEclipse上のコンソールに出力することもできます。
それについてはユークリッドさんが書いているので引用させていただきます。

yuqlid.hatenablog.com

yuqlid.hatenablog.com

場合分けで使いたい方使えばいいと思います。

単に値見たいだけならExpression機能もありますしね