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に✓をつけます.
これで割込み時にそれぞれのコールバック関数が呼ばれるようになります.
送信完了割込み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割込みを単純に書いたものではなく,開発中のボードのプログラムですのでかなり汚いことを前もって言っておきます.
では.
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は適宜変える)
とか定義しておけば少し見やすく、わかりやすくなりますね.