北の国から

忘れたことを思い出す為の記録

HALでUSARTしよう

はじめに

HALを用いてUSARTの割り込み受信,送信をしようと思います.

使用するマイコンSTM32F303K8T6,LQFP32をDIP32に変換したのを使います.

CubeMxでの設定

Pinoutタブ

今回用いるのはUSART2(Tx:A2,Rx:A3)です.

左のツリーのUSART2を"Asyncronous"(非同期)に設定します.

Configurationタブ

“Connectivity"からUSART2を選択しましょう.

“NVIC Settings"にある"USART2 global interrupt/ホニャララ"のEnableに✓をつけます.

f:id:r_u__r_u:20170404000818p:plain

これで割込み時にそれぞれのコールバック関数が呼ばれるようになります.

送信完了割込み
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle){}

受信完了割込み
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){}

また,Enableのすぐ隣にある"Preemption Priority"をデフォルトの0から1にします.

こうすることで割込みの優先度がひとつ下がり,コールバック関数内でDelay等が使えるようになる…と考えています.(割込みの競合がなくなる)


次は"Parameter Settings"タブでボーレートやデータ長などをお好みの設定にします.

プログラム上での扱い方

main関数内では以下のように記述します.

int main(){

  HAL_UART_Receive_IT(&huart2, &RxData, 1);

  while(1){
    //infinity loop
  }
}

HAL_UART_Receive_IT(&huart2, &RxData, 1); で初回の割込みの設定をしています.

データ保存先 : RxData(型はuint8_t) データサイズ : 1byte


また,コールバック関数も重要になります.

私は受信完了割り込みのコールバック関数を以下のように定義しています.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
  HAL_UART_Receive_IT(&huart2, &RxData, 1);
/*
  様々な処理
*/
}

コールバック関数内に次回用の割込みの設定を入れています.


送信の際はは以下の関数で行います.

HAL_UART_Transmit_IT(&huart2,TxData,10);

ここでTxDataは要素数10の配列です.

送信完了割込みもありますが,私は使う機械が無いため割愛します.

終わりに

見難いかと思いますがとりあえず忘れないうちにメモしました.

ここにこれを用いたコードを公開しています.

USART割込みを単純に書いたものではなく,開発中のボードのプログラムですのでかなり汚いことを前もって言っておきます.

では.

便利機能のおぼえがき

vimを分割するやつ

  • :split : 横に割れる

  • :vsplit :縦に割れる

割った画面を消すときは:qで消える

workspace切り替えるやつ

  • Ctrl+Alt+(↑or↓or→or←) : 矢印の先のworkspaceに移動
  • Shift+Ctrl+Alt+(↑or↓or→or←) : chromeとかの画面を矢印の先のworkspaceに移動させる
  • Super+S : workspaceの一覧を表示する

STM32F3 HALでエンコーダ入力

はじめに

エンコーダのカウントをしたくなった時に割と設定とか忘れがちなのでまとめときます.

CubeMx上での設定

Pinoutタブ

基本的にエンコーダでA,B相をカウントするときはCH1とCH2を使うはずです.(それ以外知らない)

なのでCH1,CH2どちらも揃っているタイマを選びます.

左側ツリーよりTIMx(xは任意の数字.TIM1とかTIM4とかいろいろあるよね)を展開し,“Combined Channels"以外を"Disable"に設定.

その後,“Combined Channels"を"Encoder Mode"に設定します.


設定すると右側のICの絵で対応しているピンが緑に変わります.

CH1はA相,CH2はB相に繋ぎます.(当然ですが逆だと値も逆になります)

Configuratinタブ

“Control"欄のTIMx(さっき設定したタイマ)を開き,"Parameter Settings"タブへ行くと,エンコーダ入力に関する諸設定ができるようになっているはずです.

僕はいつも

Period : 65535 (16bitカウンタの最大値)

Encoder Mode :Encoder Mode TI1 and TI2 (4逓倍)

の部分だけ変更しています.

プログラム上での扱い

エンコーダカウントの開始

HAL_TIM_Encoder_Start(&htimx,TIM_CHANNEL_ALL);

エンコーダカウントの停止

HAL_TIM_Encoder_Stop(&htimx,TIM_CHANNEL_ALL);

カウント値の読み込み(iは適当な変数とする)

i = TIMx -> CNT;

このようにするとエンコーダの値を取得できます.

もしかしたらもっといい値の読み方あるかもしれないので知ってる方、教えてください…

追記

値取得用関数の定義

毎回TIMx->CNTで読み込むのは見た目気持ち悪い&ぱっと見わかりにくいので

int getTIMxCNT(){
   return TIMx->CNT;
}

(xは適宜変える)
とか定義しておけば少し見やすく、わかりやすくなりますね.