2016年12月23日金曜日

[STM32マイコン]SW4STM32を使う(USB-HIDデバイス)

F401REではUSBデバイスの開発ができるのでHIDのマウスとしてPCに認識させたいと思います。

○CubeMXでUSBを使う設定にする
まず、"Pinout"タブでUSBを使う設定をします。 Peripherals >> USB_OGT_FS >> MODE を Device_Only にします。 MiddleWares >> USB_DEVICE >> Class_for_FS_IP を "Human_Interface_Device" に設定する。
さらに、USBでは正確な高速クロック(HSEの設定)が必要なため、クリスタルが必要ですが、今回使うボードにはデバッグボード上にしか必要なクリスタルがないため、それを使うよう設定します。そのため、"Pinout"タブでHSEを使う設定にします。Peripherals >> RCC >>HSE を"BYPASS_Clock_Source"に設定します。
次に、このままではエラーが出てしまうのでクロック周りの設定をしてHSEでのクロックを有効にします。"Clock configuration"タブに移動するとクロック周りの問題を治すかどうか聞かれるので’Yes’を選択すると自動で設定してくれます。
最後にジェネレートして終わりです。

○SW4STM32でプログラミング
SW4STM32を起動しインポートします。そして、main.cファイルの中のmain関数のwhileループのところに下記のようにします。
//---------------------------------
  int8_t hid_mouse[4]={0,-5,0,0};//button1-3,x,y,wheel
  while(1){
    HAL_Delay(5000);
    USBD_HID_SendReport(&hUsbDeviceFS,hid_mouse,4);
  }
//---------------------------------
このようにすると五秒に一回左にマウスポインターが動くようなマウスができます。
CubeMXで上記の設定をするとジェネレートされるコードはHIDマウスです。(デバイスディスクリプタ等がそのように設定されているため)

○STM32F401RE(Nucleo64マイコンボード)の配線
PA12ピンをUSBのD+、PA11ピンをUSBのD-、GNDをUSBのGNDに接続するが、USBのVbusは接続しません。(USBから電源を取るときはVbusをE5Vピンに接続し、リセットボタン下の電源を選ぶジャンパーをE5Vにする) また、必要なUSBケーブルは100円ショップ等で買うこともできます。大抵のケーブルはVbusが赤、D+が緑、D-が白、GNDは黒のコードですが、念のため、VbusとGNDを確かめるためUSB充電器とLEDを使って確認します。また、F401REではPA9ピンを3.3[V]ピンに接続しておきます。(F401REではこれが無いとUSBの機能が動きません)





[STM32マイコン]SW4STM32を使う(複数のADコンバータ)

F401RE(STM32系マイコン)で、SW4STM32とCubeMXを使って複数のADCをHALライブラリを用いて使おうとしたとき、情報があまりなかったので、その方法を残しておきます。

今回行う方法は、ADCを使って値を読み取るたびに、使うADCのチャンネルをセットしなおす方法です。
※HAL_ADCEx_MultiMode系の関数を使ったほうが速いかもしれないが、HALライブラリはあまり詳しいわけではなく、使い方がよく分からなかったので試すことができなかった。

まず、CubeMXでADCで使うピンを設定したら、プロジェクトをジェネレートします。

次にプログラムを行っていきます。
プログラムは使いやすいように新しい関数を作りますが、mainファイル内に自動生成された MX_ADC1_Init()関数を利用します。この関数でチャンネルを決めているのは "sConfig.Channel=ADC_CHANNEL_0;"となっている部分なので、ここを変えてチャンネルを選んで値を取得できるようにします。
[追記・訂正]以前のものだと正常に動作しない場合があったためDelayを入れ修正しました
//---------------------------
uint16_t ADCsGetValue(uint32_t ch)
{
  HAL_ADC_Stop(&hadc1);
 //------ ADC Channel Select
  ADC_ChannelConfTypeDef sConfig;
  sConfig.Channel = ch;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
 //------ ADC Read
  HAL_ADC_Start(&hadc1);
  HAL_Delay(1);
  return HAL_ADC_GetValue(&hadc1);
}
//---------------------------
今回作った関数は引数にチャンネル(ADC_CHANNEL_0等)、返り値にそのチャンネルの値を持ちます。
また、値を読んだ直後にHAL_ADC_Stopを置くと値を取得できませんでした。原因は分かりませんが、HAL_ADC_Stopまでに時間があるほうがいいようです。(DelayをStop前に置くとうまくいく)
→ StartしてからGetValueまでの間にDelayを入れるとうまくいく (おそらくStartの後AD変換が行われ、その後出ないと正確な値がGetValueで読み出せないのだと思われる)
 ↓↓
割り込みなどを使った方が良いと考えられる。





[STM32マイコン]SW4STM32を使う(ADコンバータ)

今回は、F401REでアナログ電圧を読み(ADCを使う)、それをシリアル通信でPCに表示するプログラムをSW4STM32とCubeMXを使って作成します。
※ライブラリはHALを使用

○CubeMXでADコンバータ(ADC)を使う設定にする
 前回のシリアル通信をするものに、ADCを使う設置を追加します。
 前回同様にCubeMXを起動し、LoadProjectで前回までのプロジェクトを開く。
 次に、"Pinout"タブでADCピンを割り当てる。今回は"ADC1_IN0" (F401REのPA0端子) を使う。
 左の "Configuration" >> "Peripherals" >> "ADC1" のIN0にチェックをいれる。
最後に、プロジェクトをジェネレートしなおす。

○SW4STM32の準備
SW4STM32を再起動するか、プロジェクトをリフレッシュして、プロジェクトを読み込みなおす。
エラーが出たときは、プロジェクトのCleanとBuildでエラーを消す。それでもエラーが消えないときは、プロジェクトをSW4STM32上から削除し、インポートしなおす。

○プログラミング
main.c内のmain()関数で、whileループのところに下記のように書き加えます。
//---------------------------------------------
  char str[32]={0};
  sprintf(str,"\nSTART\n");
  HAL_UART_Transmit( &huart2, str, strlen(str), 0xFFFF );

  while(1){
      HAL_ADC_Start(&hadc1);
      int val=HAL_ADC_GetValue(&hadc1);
      sprintf(str,"ADC_IN0 : %4d (%4d[mV]) \r", val, val*3300/0xfff);
      HAL_UART_Transmit( &huart2, str, strlen(str), 0xFFFF );

      HAL_ADC_Stop(&hadc1);
      HAL_Delay(1000);
  }

//----------------------------------------------
・"HAL_ADC_GetValue"で得られる値は0~4095(0xfff)で、F401REは、3.3[V] (3300[mV]) で動作しているので、"val*3300/0xfff"とすれば、[mV]で値を読み取れる。
 ※ 3.3[V] で動作しているので5[V]端子にADCの端子をつながないように注意が必要。
・ "HAL_ADC_GetValue" の前に "HAL_ADC_Start"、後に "HAL_ADC_Stop" を行わないと連続で値を読めない。
 ※ "HAL_ADC_Start"を行わないと値が読めない。

最後は、実行して、TeraTerm等で表示し、ADCが使えていることが確認できればOKです。
※ 端子に何も繋がないときは値が揺れます。

2016年12月7日水曜日

[STM32マイコン]SW4STM32を使う(シリアル通信)

前回は、SW4STM32を使って、F401REでLチカをやりましたが、今回はLEDの点滅にあわせて、PCと繋いだF401REから、シリアル通信で、ON/OFFをPCに伝える。

○TeraTermの準備
 Windowsでシリアル通信を行うために、TeraTermを用意します。
TeraTermのサイトからexeファイルをダウンロードし、インストールします。

○CubeMXでシリアル通信を使う設定にする
SW4STM32を起動し、"Window" > "Other" と進み、出てきたウィンドウで "Other" > "STM32CubeMX" と進み、CubeMXを起動する。
CubeMXのサブウィンドウが出たら、前回のプロジェクトに書き足すので "Load Project" を押し、前回作ったプロジェクトを開く。
"Pinout"タブでピンをどのように割り当てるかを決めるが、ここではF401REに付いているMini-USB端子を使って通信するので、左の "Configuration" の中のUSART2のModeをAsynchronousに設定する。(F401REが付属のデバックモジュールを介してPCと接続するのに使うピンはUSART2の為)
次に、"Configuration"タブでUSARTについて設定します。ConectivityのUSART2を押すと、 "USART2 Configuration"というウィンドウが出るので、"GPIO settings"タブでPA2/PA3ピンともプルアップし、スピードを"High"にします。
最後にジェネレートするのですが、その前にプロジェクトのmain.cファイルのバックアップを行います。Lチカのプログラムは簡単なので行わなくてもいいですが、既にあるプロジェクトに上書きする形でジェネレートするとプログラムが消えてしますことがあります。

○SW4STM32のエラー消し
元々あるプロジェクトにCubeMXを使ってジェネレートしなおした場合、SW4STM32側に追加された関数が未定義である等のエラーが出ます。このような時は、"Project"タブ > "Clean" > "Clean All Project" を行い、"Project"タブ > "Build All" を行います。ただし、これでもエラーが直らない場合、プロジェクトを削除し(ファイルそのものを消すわけではない)、もう一度インポートしなおすことで解消されます。

○プログラミング 
main.c内のmain()関数で、whileループのところに下記のように書き加えます。
//---------------------------------------------

  char str[16]={0};
  while(){
      // LED-ON
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
      sprintf(str,"ON ");
      HAL_UART_Transmit( &huart2, str, strlen(str), 0xFFFF );
      HAL_Delay(1000);
      // LED-OFF
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
      sprintf(str,"OFF ");
      HAL_UART_Transmit( &huart2, str, strlen(str), 0xFFFF );
      HAL_Delay(1000);
  }

//----------------------------------------------
printf関数でシリアル通信はできませんでしたが、sprintfは使えるので、それを使って文字列を配列に入れ、その配列をシリアル通信で送ります。
プログラムを書いたら、実行してF401REに書き込みます。

○TeraTermで表示する
まず、TeraTermを起動し("\TeraTermのあるディレクトリ\ttermpro.exe")、"シリアル"を選択し、ポートは STMicro~ となっているものを選択し、"OK" を押す。
次に、"設定" > "シリアルポート" と進み、ボー・レートを115200とする。
 ※ボーレート:CubeMX→ Configurationタブ→ USART2Configurationウィンドウ→ ParameterSettngsタブ→ BaudRate で確認可能






2016年12月5日月曜日

[STM32マイコン]SW4STM32を使う(Lチカ)

まず、SW4STM32を使った環境に慣れるためにも、はじめはLEDを点滅させるだけのプログラム(Lチカ)を動かして生きたいと思います。

○プロジェクトの作成
 SW4STM32(eclipse)を起動して、"Window" > "Show view" > "Other" と進み、さらに出てきたウィンドウで "Other" > "STM32CubeMX" と進むとSW4STM32(eclipse)の中にSTM32CubeMXのサブウィンドウが現れる。ここで、 "New Project" を押し、開いたウィンドウの"Board Selector"のタブから、"NUCLEO-F401RE" を選択 (自分の使っているものを選択) 、最後にOKを押す。すると、GUIでマイコンのI/Oなどの設定ができるようになる。
Lチカでは初期設定のままで問題ない。(ボードに載っているLEDのみ)
プロジェクトのジェネレート設定は、"Project" > "Settings" と進み、出てきたウィンドウでプロジェクトの名前を決め、"Toolchain / IDE" で "SW4STM32" を選択することで、SW4STM32でインポート可能なプロジェクトとなる。

最後に、"Project" > "Generate Code" でジェネレートする。

○SW4STM32にプロジェクトをインポート
SW4STM32で "File" > "Import" と進み、さらに出てきたウィンドウで "General" >"Existing Projects into Workspace" を選択 Nextで進み、先ほどジェネレートしたプロジェクトのフォルダー ( ”ワークスペースのディレクトリ \ プロジェクト名” など ) を選択し、Finishを押す。

○Lチカのプログラム
"Project Explorer"のサブウィンドウで "プロジェクト名" > "Src" > "main.c" と進むとmain.cを編集できる。その中のmain関数内のwhile文内に、下記を書き足す。
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
    HAL_Delay(1000);
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    HAL_Delay(1000);
次に、"Project" > "Build All" でプロジェクトをビルドする。

○Lチカの実行
まず、USBでF401REとPCをつなぐ。
次に、"Runのタブ" > "External Tools" > "External Tools Configurations" と進み、前回作ったOpenOCDを設定したものを実行する。
これで作ったものが実行されるはずだが、エラーが出たら、"Run" > "Run"か"Run" > "Debug" で実行するとなぜかうまくいくことがまれにある。

しかし、うまくいかなかったときは、どこかに間違いがあることになるのだが、よく確認 (プロジェクトを作成し直す、設定を見直す等) しても動かないときは、すべてアンインストールしてやり直す必要があるかもしれない。



次(シリアル通信)>>

[STM32マイコン]STM32のオフライン開発環境の導入3 (Toolchain等のインストール)

>前回に続き、F401REのオフライン開発環境を整えていきます。今回は、ARMマイコン用にプログラムをコンパイルすることなどができるToolchain等をインストールしていきます。

参考:http://birdhouse.hateblo.jp/entry/2016/07/28/151525

LaunchpadからToolchain 、GitHubからOpenOCDを入手し、インストールする。

次に、上記のサイトを参考にして、OpenOCDを設定する。
Eclipse(SW4STM32)を起動し、"Runのタブ" > "External Tools" > "External Tools Configurations"と進み、出てきたウィンドウの"Program"を選択し、その上のほうにある紙にプラスのついたマークをクリックする。


その後も上記のサイトを参考にするが、今回使うマイコンはF401REでF4系なので下記のように、Argumentsの"_f0.cfg" は "_f4.cfg" とする。
 最後に、Applyで適用すれば設定完了です。


<<前  次(SW4STM32でLチカ)>>