STM32 +HALでエンコーダモードを使用してみる

2020年6月11日

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

STM32のタイマーにはエンコーダモードがあります。使用例として挙げると、距離速度を計測するために使用されているモーターについているエンコーダや、磁気式の自作エンコーダの値の取得に使っています。

エンコーダモードの使い方がわかりづらかったのでまとめていきたいと思います。

使用するマイコンはSTM32F405RGTです。

 




リファレンスマニュアルを確認する

STM32F405のリファレンスマニュアルには次のように書いてあります。

RM0090より

 

RM0090より

データシートより以下のことがわかりました。

  • 2つの入力をとれる
  • 回転方向をとれる
  • AutoReloadResistorの0~設定した値(16bit)の間でカウントする
  • カウントされたデータはタイマーのカウンタレジスタの中に入る

TIM1,TIM8のカウントレジスタは以下のようになってました。

RM0090より

書き込み、読み込みが可能ということがわかりました。

あとは、HALドライバでカウントレジスタにどのようにアクセスをすればいいか、エンコーダモードをどのようにスタートさせていいかがわかれば動かせそうということがわかります。

以上のことを踏まえてSTM32CubeMxでの設定を行っていきます。

 

STM32CubeMXの設定

今回は、TIM1をエンコーダモードに設定し、エンコーダの値を確認するためにUSART3を有効化しました。

また、エンコーダモードでエンコーダのパルスをカウントした値は、0からAutoReloadResistorの設定値までの間の値を取得するようになるので最大値を16bitの最大値である65535に設定しました。

STM32CubeMx エンコーダモードの設定

ペリフェラルごとにファイルをわけるようにして、コードを生成してもらいましょう。

 

ソースコード実装

HALのドライバマニュアルを見てみると、HAL_TIM_Encoder_Startという関数でエンコーダモードをスタートさせることができるということがわかりました。

UM1725より

しかし、TIMのCNTレジスタをどのように参照すればいいのかが見つけられなかったので1生成されたソースコードから探していきたいと思います。

私が使用しているVisual Studio Codeでは、定義に移動することができるので、TIM1のインスタンスから移動していきたいと思います。

移動をしていった結果見つけることができたものは以下の通りです。

stm32f405xx.hより

TIM_TypeDef

 

データシートと見比べて、アドレスもあっていることからここで定義されているCNTアドレスにアクセスをすればよさそうということがわかりました。

また、TIM_HandleTypeDefのインスタンスにはアドレスが受け渡されているだけであり、TIM1がTIM_TypeDefで定義されていたので、TIM1->CNTのようにアクセスが可能であることがわかりました。


stm32f405xx.hより

stm32f405xx.hより

これらのことを踏まえて次の手順でエンコーダの値を取得します。

  1. TIM1のカウントレジスタからデータを読み取る
  2. TIM1のカウントレジスタの値をリセット
  3. uint16_t型の値をintf16_tで受け取る。そのため、enc_buffの値が32767以上の場合はマイナスとして受け取り、それ以外のときは、プラスとして受け取る2
  4. 取得したデータを返す

実装したソースコードは以下の通りです。

int16_t get_encoder( void )
{
  int16_t count = 0;
  uint16_t enc_buff = TIM1->CNT;
  TIM1->CNT = 0;

  if( enc_buff > 32767 ){
    count = (int16_t)enc_l_buff;
  } else {
    count = (int16_t)enc_l_buff;
  }

  return count;
}
#include ~ 
//(省略) 
// 関数のプロトタイプ宣言をちゃんとしておくこと。
 
int main()
  // initは省略


  /* USER CODE BEGIN 2 */
  setbuf( stdout, NULL );
 int32_t count_total = 0;
  HAL_TIM_Encoder_Start( &htim1, TIM_CHANNEL_ALL ); // encoder start
  /* USER CODE END 2 */

  while( 1 ) 
  {
    printf( "encoder = %drn", get_encoder(), count_total );
    count_total += get_encoder();
  }
}

これで、取得時、取得データの合計を表示することができるはずです。

 

さいごに

エンコーダモードは、ちゃんとデータシートを読み、レジスタを確認してHALドライバの中身をみていくということをしないと使えないため、他の機能を使うよりも難しいです。

データシートを読むことの大切さがよくわかりました。

 

参考文献

UM1725 User Manual

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

 

  1. 私が見落としているだけの可能性があるので、ここに書いてあるなどの情報があれば教えていただきたいです。
  2. 回転方向を変えたいときは、-1をかければよい