STM32勉強メモ12(スイッチ入力長押し、短押し処理1)
スイッチの入力とLED出力1.本日の内容 (1) STM32マイコン(nucleo f401RE)を使用して、 スイッチを押してから1秒未満で離した場合は、LED点灯 スイッチを押してから1秒以上経って離した場合は、LED点滅させる の処理を作成する。2.内容(1) やる内容の詳細 ・STM32マイコン(nucleo f401RE)を使用 ・スイッチを押したときの、押している秒数で、処理を変える。 →スイッチを押してから1秒未満で離した場合は、LED点灯 →スイッチを押してから1秒以上経って離した場合は、LED点滅させる ・点滅は、1秒ごとに、点灯/消灯を繰り返す。 ・メイン処理は、main.cではなく、self_main.c、self_main.hファイルを作成する。 ・led.cとled.hとtypedf.hファイルは、下記で作成したファイルを使用する。 →作成したファイル: 動作動画:https://youtube.com/shorts/WBtNI9qN8jQ?feature=share ショートだと埋め込めないみたいなので、URLを置いておく。(2) 使用部品個数部品名型番1USBケーブルUSBミニBタイプ1mbed(マイコンボード)nucleo f401RE(3) STM32CubeMXの設定、プログラムを出力 (a)使用ピンを設定 ・PA5:GPIO_Output ・PA6:GPIO_Output ・PC13:GPIO_Input (b)使用するピンの名前を変更 ・PA5→右クリック→Enter Username→LED1とする。 ・PA6→右クリック→Enter Username→LED2とする。 ・PC13→右クリック→Enter Username→KEY1とする。 (c) 割り込み設定 ・System Core → RCCをクリック ・High Speed Clock(HSE)を、Crystal/Ceramic Resonatorに設定 →内部水晶振動子などを使用する。 →外部からクロックを入力する場合は、「BYPASS Clock Source」に設定。 (d) タイマーの設定(1秒に1回動作) ・TimersのTIM3をクリック ・Clock Source を Internal Clock に設定 ・Parameter Settingsタブをクリック ・Prescalerを 1000-1 ・Counter Periodを 16000 に設定 ・TimersのTIM5をクリック(10msに1回動作) ・Clock Source を Internal Clock に設定 ・Parameter Settingsタブをクリック ・Prescalerを 10-1 ・Counter Periodを 16000 に設定 ・NVIC Settingsタブをクリック ・Enableのチェックを入れる。 ・Preemption Priority を1に変更する。 ※「⚠」のマークが表示されていたり、黄色くなっている場所は 設定によっては機能が競合するということ。 (d)プログラムの出力 ・Project Maagerを選択 ・Project Nameにプログラムの名前を入力:SW_LED7 ※スペース、空白文字、日本語を含めるとエラーになる場合があるので、使用しない。 ・Project Location:プロジェクトを保存する場所 ・Application Structure:Advanced (出力するフォルダの構成を選択) ・Toolchain/IDE:TrueSTUDIO(今回は、AtoricTrueStdioを使用するため) (f)GENERATE CODEで、コードを出力 (g)Open pROJECTをクリックすると、AtricTrueStdioが自動的に起動される。(4) AtricTrueStdioでプログラム作成 (a) AtricTrueStdioから開く場合(上記(g)をした場合は不要) ・AtricTrueStdioを起動 ・インポート元のディレクトリをクリック ・CubeMXで作成した場所を指定 ・フォルダーにSW_LED7(作成したプロジェクトの名前)が表示 ・チェックされているのを確認して、終了をクリック (b) プログラムの書き込み ・トンカチマークをクリックして、ビルドする。 ・エラーが出ないことを確認する。今回の内容はここから ・下記プログラムを記載する。//self_main.cファイルの作成//ーーープログラム開始ーーーーーーー///** ***************************** *//** * @file self_main.c * @brief メイン処理 * @brief Compiler : Atollic True Studio for STM32 9.0.0 * @brief CPU : STM32F401 *//** ******************************* *//* ********************************** */// インクルード ファイル *//* ************************************ */#include "typedef.h" //基本型変数定義ヘッダファイルのインクルード#include "led.h" //LED制御ヘッダファイルのインクルード#include "main.h" //STM32ヘッダファイルのインクルード#include "self_main.h" //ヘッダファイルのインクルード/** ************************* *//** 外部定義変数 *//** ******************************* *//** *************************** *//** 内部定義変数 *//** **************************** *///割り込み処理宣言TIM_HandleTypeDef htim3; //TIM3を使用TIM_HandleTypeDef htim5; //TIM5を使用/** ************************* *//** 関数の作成 *//** ************************* *//** ******************* *//** * Selfmain関数 :自分で作成するメイン処理* @param void : none * @return void : none *//** ******************** */void self_main(){ //初期化処理 g_ModeSelect.neStates = LEDOFF; //モードステートをLEDOFFに設定 g_ModeLedCtrl.Led1_Bli_Ena = false; //LED1の点滅フラグをなしに設定 HAL_TIM_Base_Start_IT(&htim3); //htim3の割り込み処理開始 HAL_TIM_Base_Start_IT(&htim5); //htim5の割り込み処理開始 while(1){ switch(g_KeyCtrlInf.KeyStates){ //スイッチの動作ステート確認 case noKey: //動作ステート押下なしの時 //なにもしない。 break; case Key_Short: //動作ステート短押しの時 g_ModeSelect.neStates = LEDON; //次のLED動作モードをLED点灯モードに変更 break; case Key_Long: //動作ステート長押しの時 g_ModeSelect.neStates = LEDBL; //次のLED動作モードをLED点滅に変更 break; } //スイッチの動作ステート確認終了 //動作モード処理 if(g_ModeSelect.cuStates == LEDON){ //現在のモードがLED点灯モードの時 g_ModeLedCtrl.Led1_Bli_Ena = false; //LED1点滅OFF Led1On(); //LED1点灯 }else if(g_ModeSelect.cuStates == LEDBL){ //LED点滅モードの時 g_ModeLedCtrl.Led1_Bli_Ena = true; //LED1点滅開始 }else{ //モード選択なし時 //何もしない。 } //動作モード更新処理 if(g_ModeSelect.cuStates != g_ModeSelect.neStates){ g_ModeSelect.cuStates = g_ModeSelect.neStates; } }}//割り込み処理void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ __IO uint8_t button_state = 0; if(htim == &htim3){ //1sごとに実行 if(g_ModeLedCtrl.Led1_Bli_Ena == true){ Led1OnOff(); //LED点滅関数の実行 } } if(htim == &htim5){//10msごとに実行 //スイッチの状態確認 //スイッチ入力 PC_13のスイッチのON/OFF確認 button_state = HAL_GPIO_ReadPin(SW_GPIO_Port,SW_Pin); UCHAR countTime = 100; //長押し時間 if(button_state == 0){ //キー押下時処理 g_KeyCtrlInf.usKEY_OnTim++; //キー押下カウントを+1 }else{ //キー押下無し時処理 //スイッチ短押し時 if(g_KeyCtrlInf.usKEY_OnTim > 0 && g_KeyCtrlInf.usKEY_OnTim <= countTime){ //キーステートをキー短押しに変更 g_KeyCtrlInf.KeyStates =Key_Short; g_KeyCtrlInf.usKEY_OnTim = 0; //キー押下カウントをリセット }else if(g_KeyCtrlInf.usKEY_OnTim > countTime){ //スイッチ長押し時 //キーステートをキー長押しに変更 g_KeyCtrlInf.KeyStates =Key_Long; g_KeyCtrlInf.usKEY_OnTim = 0; //キー押下カウントをリセット }else { //デフォルト(スイッチ押下無し時) //キーステートをキー押下無しに変更 g_KeyCtrlInf.KeyStates =noKey; } } //ボタン押下時処理終了 } //htim5終了}/* **** ファイルの最後 ( self_main.c ) ********************************* *///ーーープログラム終了ーーーーーーー////main_self.hファイルの作成//ーーープログラム開始ーーーーーーー///** ************************* *//** * @file mode.h * @brief Mode制御ヘッダ * @brief Compiler : Atollic True Studio for STM32 9.0.0 * @brief CPU : STM32F401RE *//** ************************** */#ifndef SELF_MAIN_H ///<SELF_MAIN_H未定義?#define SELF_MAIN_H ///<SELF_MAIN_H 定義済み!!/* **************************** *//* 定数値の定義 /* **************************** *//* **************************** *//* 式、関数の置き換え /* **************************** *//* **************************** *//* 構造体の定義 /* **************************** */typedef enum{ noKey=0 //キー押下無し ,Key_Short //キー短押し ,Key_Long //キー長押し}KEYSTATUS;//スイッチ選択用構造体typedef struct{ KEYSTATUS KeyStates; //キーステータスの格納 USHORT usKEY_OnTim; //キー押下時間測定}KEY_CTRL_INF;//モードステート用構造体typedef struct{ LEDONOFF neStates; LEDONOFF cuStates;}MODE_SELECT;/* ****************************************** *//* 外部変数の定義 /* ****************************************** */KEY_CTRL_INF g_KeyCtrlInf; //キーステート構造体MDOE_LED_CTRL g_ModeLedCtrl; //MODE LEDステート管理用構造体MODE_SELECT g_ModeSelect; //MODE変更構造体/* *************************************** *//* 関数のプロトタイプ宣言 /* *************************************** */void self_main();//void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//割り込み処理#endif ///<SELF_MAIN_H 未定義 End/* **** ファイルの最後 ( self_main.h ) ****************** *///ーーープログラム終了ーーーーーーー////main.cファイルのプログラム//今回は、基本のmainループは、別ファイルに作成したが、//それをmain.cで使えるようにする必要がある。//main.cファイル//main_self.hファイルの作成/* USER CODE BEGIN Includes */#include "typedef.h" //基本型変数定義ヘッダファイルのインクルード#include "led.h" //LED制御ヘッダファイルのインクルード#include "self_main.h" //ヘッダファイルのインクルード/* USER CODE END Includes */ /* USER CODE BEGIN 2 */ self_main(); /* USER CODE END 2 *///ーーープログラム終了ーーーーーーー//(5) プログラムの説明 (a)割り込み処理のフロー※フローだと150になっているが、実際は100・スイッチがONになったら、カウントを開始する。・押している時間を、割り込み処理を10msごとに、カウントを+1・そのカウントの数で、長押しか、短押しかを判断。 (b) メインループ処理のフロー ・スイッチの動作ステートによって、モードを変更・LEDONの場合とLED点滅モードを変化させる。 (c) 処理内容参考:・C++日本語リファレンス(uint8_t)・STM32でUARTをやってみる1・STM32CubeIDEを使ってみよう How To STM32CubeIDE 日本語版 (5) UARTを使ってみよう・マイクロマウス研修(kora編)[23] STM32マイコンでシリアル通信・C言語ゼミ