STM32 + LL のUSARTでsnanf(float型対応)が動くようにしてみる

2020年6月11日

STM32マイコンのペリフェラル関連記事を一覧にまとめました。

HALAPIを使用したものではscanfの実装を行いましたが、LLAPIではscanfの実装方法を書いていなかったので書いていこうと思います。

それぞれの記事

HAL API Version

LL API Version(STM32CubeMXの設定はこれと同じためこの記事では省略します。)

 




リファレンスマニュアルを読む

RM0090 リファレンスマニュアル

今回必要なところはここです。この手順に沿ってプログラムを書くことで動作をさせることができます。STM32CubeMXで生成されたソースではREビットがセットされていないので自分でセットする必要があります。使用するレジスタはprintfの実装の記事と同様なため省略します。

今回紹介するプログラムでは、フレームエラー、オーバーランエラーなどの検出を行うことはしないので必要な場合は各自でセットしていただければと思います。

 

ソースコードの実装

実装

usart.cのuser code beginの間に次のソースを実装しました。

void USART3_ReadEnable(void)
{
  LL_USART_EnableDirectionRx(USART3);
}

uint8_t USART3_ReceiveData8(void)
{
  uint8_t data = 0;
  while (LL_USART_IsActiveFlag_RXNE(USART3) == RESET);
  data = LL_USART_ReceiveData8(USART3);
  LL_USART_ClearFlag_RXNE(USART3);
  return data;
}

void USART3_TransmmitByte(uint8_t ch)
{
  LL_USART_TransmitData8(USART3, ch);
  while (LL_USART_IsActiveFlag_TXE(USART3) == RESET);
}

USART3_ReadEnable関数でREビットを有効化、USART3_ReceiveData8関数でデータの読み込みを行っています。USART3_TransmmitByte関数は今回printfを使用するため載せておきました。

 

リンカオプションを追加する(float型に対応する)

makefileを使用している方は、makefileのLDFLAGSの最後に以下の文字列を追加してください。

-u _scanf_float

printfと同様に、float型に対応するためにはリンカオプションを増やす必要性があります。

STM32CubeIDEの場合は上のツールバーの[Project]→[Properties]から以下の場所に移動してチェックボックスにチェックを入れることでfloat型に対応することが可能になります。

ver1.00ではLLライブラリの生成されたソースでコンパイルが通らないバグがありましたが、アップデートしてから依然あったバグが再発しないためCubeIDEに乗り換えるか検討中です。

 

使い方

マクロ定義でio_putcharをオーバーライドする。

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdint.h>

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int f getc(FILE* f)
#endif

void __io_putchar(uint8_t ch) {
  USART3_TransmmitByte(ch);
}

int __io_getchar(void) {
  uint8_t data = 0;
  data = USART3_ReceiveData8();
  return data;
}
/* USER CODE END Includes */

確認(main関数内のwhileの前に実装)

  /* USER CODE BEGIN 2 */

  USART3_ReadEnable();

  setbuf(stdout, NULL);
  setbuf(stdin, NULL);

  char ch[16];
  float data;
  printf("read string = rn");
  scanf("%s",ch);
  printf("%srn",ch);
  printf("get float number = rn");
  scanf("%f",&data);
  printf("%frn", data);

  /* USER CODE END 2 */

これで、ちゃんと文字列、数値の読み込みして出力ができれば実装成功です。

 

おわりに

LLAPIでscanfを使用することができるようになりました。マイクロマウス競技の場合は通信は基本的に送信があればいいですがマイコンを使用して何かしたいときはマイコンにPCからデータを送信してなにかするということができないと不便なので実装をしてみました。

次回は、LLAPI で SPI通信の記事を書く予定です。

 

参考文献

RM0090 リファレンスマニュアル