STM32 (スイッチ長押し/短押し制御)
1.本日の内容
(1) STM32マイコン(nucleof401re)を使用して、
スイッチの長押し/短押しの判定を行う。
・目次
2.内容
(1) やる内容の詳細
・nucleof401REスイッチのスイッチ(青ボタン)の長押し/短押し制御を行う。
・長押し時:LEDの点滅/LED消灯
・短押し時:LED点灯/消灯
を行う。
スイッチを押した時の、状態の変化を状態遷移図で示す。
これを元に、状態遷移表を作成する。
・MODE1:LED点灯
・MODE2:LED消灯
・MODE3:LED点滅
状態遷移図及び状態遷移表については下記が参考になります。
・状態遷移表を使用した要求分析モデル:状態遷移表による設計手法(3)(1/3 ページ) - MONOist
・UMLステートマシンと状態遷移図 - astah-info
・設計 | PlantUMLによる状態遷移図の書き方, 状態遷移表からのテスト抽出方法 - わくわくBank
(2) 使用部品
個数 | 部品名 | 型番 |
---|---|---|
1 | 接続ケーブル | ジャンパーワイヤ |
1 | mbed(マイコンボード) | nucleo f401RE |
1 | USBケーブル | USBミニBタイプ |
(2) CubeIDEの設定
ピン及び、基本設定として、CubeIDEで下記設定を行う。
・LEDのGPIO出力設定(PA5:GPIO_OUT)
・KEYのGPIO入力設定(PC13:GPIO_IN)
・タイマ割り込み設定(TIM3)
→1ms毎に割り込み発生
・デバック用にUART設定(UART2)
→9600BPS/s
下記画像を参考
(画像ではLED制御作成後、AD変換とLCD制御を追加予定の為、そのピン設定も含まれている)
詳細は、下記記事を参照。
下記には、CubeMXの設定について、それぞれ詳細が記載されている。
CubeIDEも同じ設定を行う。
LED及びボタン設定について
・STM32マイコン_5(スイッチ入力とLED点灯、消灯) - Project_OKI’s diary
タイマ割り込みの設定について
・STM32マイコン_9(タイマ割り込み:LED点滅) - Project_OKI’s diary
デバック用printfについて
・STM32マイコン_12(printfの導入) - Project_OKI’s diary
(3) プログラムの作成
今回は、下記ファイルを作成する。
・割り込み作成用ファイル :IntR.c/IntR.h
→参考:STM32マイコン26(割り込み:TIM3_IRQHandler)
・キー制御用ファイル :key_ctrl.c/key_ctrl.h
→参考:STM32マイコン_16(レジスタ操作でスイッチ入力) - Project_OKI’s diary
・led制御用ファイル :led.c/led.h
→参考:STM32マイコン_10(レジスタ操作でLED点滅) - Project_OKI’s diary
STM32マイコン_15(レジスタ操作でLED点滅2) - Project_OKI’s diary
・printf用ファイル :printf.c/printf.h
→参考:STM32マイコン_12(printfの導入) - Project_OKI’s diary
・メイン処理作成用ファイル :self_main.c/self_main.h
・基本型設定用ファイル :typedef.h
・STM32レジスタ設定ファイル:STMSys.h
→参考:STM32マイコン_16(レジスタ操作でスイッチ入力) - Project_OKI’s diary
今回のファイルは、JAVADOCの形式に従ってコメントを書く。
これで書くと、doxygenによって、コードからドキュメントを生成することが可能になる。
JAVADOCについて参考:
・いまさら聞けない「Javadoc」と「アノテーション」入門:【改訂版】Eclipseではじめるプログラミング(22)(1/4 ページ) - @IT
プログラムのキー入力に関するざっくりとした流れ
全体的な関数の紐づけ
///main.c (CubeIDEによって自動生成)のユーザー書き込み部分
/* USER CODE BEGIN Includes */ #include "self_main.h" #include "printf.h" /* USER CODE END Includes */
/* USER CODE BEGIN Init */ setbuf(stdout,NULL); /* USER CODE END Init */
/* USER CODE BEGIN 2 */ self_main(); /* USER CODE END 2 */
///stm32f4xx_it.c (割り込みについて記載)
/* USER CODE BEGIN Includes */ #include "typedef.h" ///< 基本型 #include "IntR.h" ///< 割り込み /* USER CODE END Includes */
/* USER CODE BEGIN TIM3_IRQn 1 */ Tim3_Int(); ///< Tim割り込み処理 /* USER CODE END TIM3_IRQn 1 */
///self_main.c (メイン処理、main.cとは別に、自分で書き換えやすいように作成)
/** *********************************************** */ /** * @file self_main.c * @brief メイン処理 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE */ /** *********************************************** */ //インクルード ファイル #include "typedef.h" ///< 基本型 #include "STMLib/STMSys.h" ///< STM32 基本制御 #include "IntR.h" ///< 割り込み #include "key_ctrl.h" ///< キー入力制御 #include "printf.h" ///< printf制御 #include "self_main.h" ///< selfメイン処理 #include "led.h" ///< LED制御 // 外部定義変数 volatile TSysCtrlInf GSysCtrlInf; ///< システム制御情報 volatile TKeyCtrlInf GKeyCtrlInf; ///< キー制御情報 // 内部関数のプロトタイプ宣言
void MainLoop(void); ///< メインループ処理 /** ************************************************************** */ /** * メイン関数 * @param void : None * @return void : None */ /** ************************************************************** */ int self_main( void ) { __disable_irq(); ///<割込み禁止 InitData(); ///< データ初期化 InitSystem(); ///< STM制御初期化 __enable_irq(); ///<割込み許可 MainLoop(); ///< メインループ return( 0 ); ///< 結果を返す } /** ************************************ */ /** * データ初期化 * @param void : None * @return void : None */ /** ************************************ */ void InitData( void ) { ///モード制御情報初期化 GSysCtrlInf.eCMode = INIT; GSysCtrlInf.eNMode = INIT; ///キー制御情報初期化 Key_Init(); } #if 1 /** ************************************ */ /** * メインループ * @param void : None * @return void : None */ /** ************************************ */ void MainLoop( void ) { ///キー監視開始 GKeyCtrlInf.key1_LongWatchEna = true; /** メインループ開始 ********************** */ while( 1 ) { /** 各動作モード処理の呼び出し **** */ switch( GSysCtrlInf.eCMode ) { ///< 動作モード確認 case INIT: ///< IDLEモード選択 IdleMode_Proc();///< IDLEモードメイン処理 break; case LCD_FOR: ///< LCD表示モード選択 LCD_For_Proc(); ///< LCD表示モードメイン処理 break; case LCD_REV: ///< LCD表示反転モード選択 LCD_Rev_Proc(); ///< LCD反転表示モードメイン処理 break; default: ///< その他 GSysCtrlInf.eNMode = INIT; ///< IDLEモードへ break; } /**現動作モード変化時更新 ******************** */ if ( GSysCtrlInf.eCMode != GSysCtrlInf.eNMode ) {
///現動作モードを更新
GSysCtrlInf.eCMode = GSysCtrlInf.eNMode; } } } /** ************************************ */ /** * IDLEモード処理 * @param void : None * @return void : None */ /** ************************************ */ void IdleMode_Proc(){ UCHAR ucKey; ///< キー入力 Led1(HIGH); ///< LED1点灯 ucKey = Key_Proc(); ///< キー入力確認 ///キー入力確認 if(ucKey == KEY1_SHORT){ ///< KEY1短押し時 GSysCtrlInf.eNMode = LCD_FOR; ///< LCD表示モードに遷移する。 }else{ //何もしない。 } } /** ************************************ */ /** * LCD表示モードメイン処理 * @param void : None * @return void : None */ /** ************************************ */ void LCD_For_Proc(){ UCHAR ucKey; ///< キー入力 Led1(LOW); ///< LED1消灯 ucKey = Key_Proc(); ///< キー入力確認 if(ucKey == KEY1_SHORT){ ///< KEY1短押し時 GSysCtrlInf.eNMode = INIT; ///< IDLEモードへ遷移 }else if(ucKey == KEY1_LONG){ ///< KEY1長押し時 GSysCtrlInf.eNMode = LCD_REV; ///< LCD反転表示モードへ遷移 } } /** ************************************ */ /** * LCD反転表示モードメイン処理 * @param void : None * @return void : None */ /** ************************************ */ void LCD_Rev_Proc(){ UCHAR ucKey; ///< キー入力 ledctrl.led1blif=true; ///< LED点滅フラグON(LED点滅開始) ucKey = Key_Proc(); ///< キー入力確認 if(ucKey == KEY1_SHORT){ ///< KEY1短押し時 ledctrl.led1blif=false; ///< LED点滅フラグOFF GSysCtrlInf.eNMode = INIT; ///< IDLEモードへ遷移 }else if(ucKey == KEY1_LONG){ ///< KEY1長押し時 ledctrl.led1blif=false; ///< LED点滅フラグOFF GSysCtrlInf.eNMode = LCD_FOR;///< LCD表示モードへ遷移 } } #endif
///self_main.h (メイン処理のヘッダファイル)
/** *********************************************** */ /** * @file self_main.h * @brief STM32ソフトメイン * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE */ /** *********************************************** */ #ifndef MAIN_H #define MAIN_H
///入力キー #define PORT_KEY1 KEY1_GPIO_Port ///< KEY1 入力ポート #define BIT_KEY1 KEY1_Pin ///< KEY1 入力ビット #define PORT_KEY2 KEY2_GPIO_Port ///< KEY2 入力ポート #define BIT_KEY2 KEY2_Pin ///< KEY2 入力ビット #define PORT_KEY3 KEY3_GPIO_Port ///< KEY3 入力ポート #define BIT_KEY3 KEY3_Pin ///< KEY3 入力ビット
///メイン動作モード定義 typedef enum { INIT=0, ///< 初期モード LCD_FOR, ///< LCD電圧表示モード LCD_REV, ///< LCD電圧反転表示モード MODE3 ///< MODE3モード } TMMODE; ///システム制御用構造体 typedef struct { /** メイン動作モード&ステート ************** */ TMMODE eCMode; ///< 現動作モード TMMODE eNMode; ///< 次動作モード } TSysCtrlInf; extern volatile TSysCtrlInf GSysCtrlInf; ///< システム制御情報 //関数のプロトタイプ宣言
extern int self_main(void ); ///< メイン処理 extern void InitData(void); ///< データ初期化処理 extern void MainLoop(void ); ///< メインループ処理 extern void IdleMode_Proc(void); ///< 初期IDLEモード extern void LCD_For_Proc(void); ///< LCD表示モード extern void LCD_Rev_Proc(void); ///< LCD表示モード #endif
///IntR.c (割り込み用ファイルの作成)
/** *********************************************** */ /** * @file IntR.c * @brief 割り込み制御 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE * @date $LastChangedDate : 2023/03/21 $ */ /** *********************************************** */ #include "typedef.h" ///< 基本型 #include "STMLib/STMSys.h" ///< STMLib用 #include "key_ctrl.h" ///< キー入力制御 #include "IntR.h" ///< 割り込み制御 #include "main.h" ///< メイン処理
#include "led.h" ///< led制御 #include "printf.h" ///< printf制御 /** *************************************************** */ /** グローバル変数定 */ /** *************************************************** */ ///構造体宣言 volatile TTimCtrlInf GTimCtrlInf; ///ハンドラ宣言 extern TIM_HandleTypeDef htim3; /* ***************************************************** */ /** STM32 関数作成 */ /* ***************************************************** */
/* ***************************************************** */
/** * システム初期化実行 * @param void : None * @return void : None */ /* ***************************************************** */
void InitSystem() { //Timer3割り込み開始 HAL_TIM_Base_Start_IT(&htim3); } /* ***************************************************** */
/** * TIM3割り込み処理(1msごとに割り込み) * @param void : None * @return void : None */ /* ***************************************************** */
void Tim3_Int() { /// 5ms経過毎の処理 GTimCtrlInf.uc5msCnt++; ///< 5msカウンタを更新 GTimCtrlInf.uc1sCnt++; ///< 1sカウンタを更新 /// 5ms時実行 if(GTimCtrlInf.uc5msCnt >= TIM5MS_CNT_VAL){ GTimCtrlInf.uc5msCnt = 0; ///<5msカウンタ初期化 Key_Input(); ///<キー入力制御 } ///1s時実行 if(GTimCtrlInf.uc1sCnt >= TIM1S_CNT_VAL){ GTimCtrlInf.uc1sCnt = 0; ///< 1sカウンタ初期化 Led1Blink(); ///< LED1反転処理 } }
///IntR.h (割り込み用ヘッダファイル)
/** *********************************************** */ /** * @file IntR.h * @brief 割り込み制御 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE * @date $LastChangedDate : 2023/03/21 $ */ /** *********************************************** */ #ifndef INTR_H #define INTR_H
/** *********************************************** */
/* defineの定義 */
/** *********************************************** */ #define TIM5MS_CNT_VAL ( 5 ) ///< 100msタイマ値(1ms*5=5ms) #define TIM1S_CNT_VAL ( 1000 ) ///< 1sタイマ値(1ms*1000=1s) /** *********************************************** */ /* 構造体の定義 */ /** *********************************************** */ /// タイマ制御情報 構造体の定義 typedef struct { /** タイマ制御情報 ***************** */ UCHAR uc5msCnt; ///< 5msカウンタ UINT uc1sCnt; ///< 1s カウンタ } TTimCtrlInf; /** *********************************************** */ /* 外部変数の定義 */ /** *********************************************** */ extern volatile TTimCtrlInf GTimCtrlInf; ///< タイマ制御情報 /** *********************************************** */ /* プロトタイプ宣言 */ /** *********************************************** */ extern void Tim3_Int(); extern void InitSystem(); #endif
///key_ctrl.c (キー制御用ファイル)
/** *********************************************** */ /** * @file key_ctrl.c * @brief キー入力制御 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE * @date $LastChangedDate : 2023/03/21 $ */ /** *********************************************** */ /** *********************************************** */ /** インクルードファイル */ /** *********************************************** */ #include "typedef.h" ///< 基本型 #include "key_ctrl.h" ///< キー入力制御API処理 #include "self_main.h" ///< メイン処理 #include "STMLib/STMSys.h" ///< STM32 基本制御 #include "printf.h" ///< printf制御(デバック用) /** *********************************************** */ /** 内部関数のプロトタイプ宣言 */ /** *********************************************** */ extern void Key_DatSet( UCHAR ucDat ); ///< キー入力バッファデータ格納 extern UCHAR Key_DatGet( void ); ///< キー入力バッファからデータ取得 /** ************************************************************** */ /** * キー入力情報の初期化 * @param void : None * @return void : None */ /** ************************************************************** */ void Key_Init( void ) { UCHAR ucCnt; ///< ループカウンタ /** キー入力状態の初期化**************************/ GKeyCtrlInf.ucState = KEYS_IDLE; ///< キー入力ステート GKeyCtrlInf.ucInp = 0; ///< キー入力状態 GKeyCtrlInf.ucPrev = 0; ///< キー入力状態(前回) GKeyCtrlInf.ucFix = 0; ///< キー入力状態(確定) GKeyCtrlInf.ucTimCnt = 0; ///< チャタリング除去用カウンタ /**キー入力リングバッファの初期化 ****************/ GKeyCtrlInf.ucWp = 0; ///< ライト位置 GKeyCtrlInf.ucRp = 0; ///< リード位置
///バッファサイズ分のループ for( ucCnt=0; ucCnt < KEY_BUFF_SIZE; ucCnt++ ) {
GKeyCtrlInf.ucBuff[ucCnt] = 0; ///< 0クリア } /** キー長押し用カウンタ初期化*******************/ GKeyCtrlInf.Key1_OnTimCnt = 0; ///< キー1長押し時間カウンタ /** キー長押し検出フラグ初期化*******************/ GKeyCtrlInf.eKey1_Det =0; ///< キー1長押し検出フラグ初期化 } /** ************************************************************** */ /** * キー入力 * @param void : None * @return USHORT : キー入力値 */ /** ************************************************************** */ USHORT Key_In(void) { volatile USHORT usKey1; ///< KEY1入力用変数 USHORT usKey = 0; ///< KEY store usKey1 = KEY1_IN(); ///< KEY1入力 ///<キー入力データを取得 usKey = (usKey1<<KEY1SFT); return( usKey ); ///<キー入力を返す } /** ************************************************************** */ /** * キー入力制御(5ms毎に呼び出される) * @param void : None * @return void : None */ /** ************************************************************** */ void Key_Input( void ) { USHORT ucKey1; ///< 入力データ変数
ucKey1 = Key_In(); ///< キー入力ポート1をリード:ON時:BIT1_KEY1を取得 GKeyCtrlInf.ucInp = KEY_NONE; ///< キー入力状態をクリア
/// KEY1ON時:KEYビットを設定
GKeyCtrlInf.ucInp |= (ucKey1 & BIT_KEY1 )? KEY1_SET : KEY_NONE; if ( GKeyCtrlInf.ucState == KEYS_IDLE ) {///< キー入力状態変化:待ち時
///< キー入力状態変化時
if ( GKeyCtrlInf.ucInp != GKeyCtrlInf.ucPrev ) { GKeyCtrlInf.ucPrev = GKeyCtrlInf.ucInp; ///< キー入力状態を更新 GKeyCtrlInf.ucTimCnt = 0;///< チャタリング除去カウンタをクリア GKeyCtrlInf.ucState = KEYS_CHG; ///< ステート=キー入力状態変化 }else { ///< キー入力状態変化なし時 /** キー長押し確認*********************/ if ( GKeyCtrlInf.ucFix & KEY1_SET ) { ///< KEY1 ON時
///< カウント可能時
if ( GKeyCtrlInf.Key1_OnTimCnt < 0xffff ) { GKeyCtrlInf.Key1_OnTimCnt++;///< ON時間を更新 } } } }else { GKeyCtrlInf.ucTimCnt++; ///< チャタリング除去カウンタを更新 if ( GKeyCtrlInf.ucInp != GKeyCtrlInf.ucPrev ) {
/// キー入力状態を更新 GKeyCtrlInf.ucPrev = GKeyCtrlInf.ucInp; GKeyCtrlInf.ucTimCnt = 0;///< 除去カウンタクリア }else if (GKeyCtrlInf.ucTimCnt >= KEY_CHATTER_REMOVE_TIM_CNT) { /** KEY1の状態変化確認 ******************/ if ( (GKeyCtrlInf.ucFix & KEY1_SET) != (GKeyCtrlInf.ucInp & KEY1_SET) ) { /** キーコード確認***********************/
///< KEY1状態 OFF=>ON時
if ( ( GKeyCtrlInf.ucFix & KEY1_SET ) == 0 ) { Key_DatSet( KEY1_ON ); ///< KEY1 ONコード格納 } else {///< KEY1状態 ON =>OFF Key_DatSet( KEY1_OFF ); ///< KEY1 OFFコード格納 } } /// キー入力状態(確定)を更新
/// ステート=キー入力状態変化待ち
/// チャタリング除去カウンタをクリア
GKeyCtrlInf.ucFix = GKeyCtrlInf.ucInp; GKeyCtrlInf.ucState = KEYS_IDLE; GKeyCtrlInf.ucTimCnt = 0; } } } /** ************************************************************** */ /** * キー入力データの取得 * @param void : None * @return UCHAR : ==KEY_NONE: キー入力データなし<BR> * : !=KEY_NONE: キー入力コード */ /** ************************************************************** */ UCHAR Key_Proc( void ) { UCHAR ucKey; ///< キー入力 ucKey = Key_DatGet(); ///< キー入力データの取得 /** KEY1 ON/OFF確認 ***********************************/ if ( (ucKey == KEY1_ON) || (ucKey == KEY1_OFF) ) {
GKeyCtrlInf.Key1_OnTimCnt = 0; ///< KEY1 ON時間(5ms単位)クリア } ///< キー入力なし時かつ
///< キー長短押し未検出かつ
///< 長押し時間経過時 if ( ( ucKey == KEY_NONE ) && ( GKeyCtrlInf.eKey1_Det == false ) && ( GKeyCtrlInf.Key1_OnTimCnt >= TIM_KEY_LONG ) ) { GKeyCtrlInf.eKey1_Det = ON; ///< キー長短押し検出 ucKey = KEY1_LONG; ///< キー長押し検出 } /** KEY1 短押し検出 ************************/
/// KEY1 OFF時かつ
/// 長押し時間未経過時
if ( ( ucKey == KEY1_OFF ) && ( GKeyCtrlInf.Key1_OnTimCnt < TIM_KEY_LONG ) ) { ///キー長短押し検出
/// キー長短押し未検出時 if ( GKeyCtrlInf.eKey1_Det == false ) { ucKey = KEY1_SHORT;///< キー短押しコードを格納 } else { ///< キー長短押し検出時
/// キー長短押し未検出に設定
GKeyCtrlInf.eKey1_Det = OFF; } } return( ucKey ); ///< キーデータを返す } /** ************************************************************** */ /** * キー入力バッファにデータを格納 * @param ucDat : キーデータ * @return void : None */ /** ************************************************************** */ void Key_DatSet( UCHAR ucDat ) { UCHAR ucWp; __disable_irq(); ///< 割込み禁止 /** 位置(次)の更新 *******************************/ ucWp = ( GKeyCtrlInf.ucWp + 1 ); ucWp = ( ucWp >= KEY_BUFF_SIZE )? 0 : ucWp; ///< 範囲チェック /** バッファフル確認 ************************************/ if ( ucWp == GKeyCtrlInf.ucRp ) { ///< バッファフル時 } else { ///< バッファに空きあり時
///< キーデータを格納
///< 位置を更新 GKeyCtrlInf.ucBuff[GKeyCtrlInf.ucWp] = ucDat; GKeyCtrlInf.ucWp = ucWp; } __enable_irq(); ///< 割込み許可 } /** ************************************************************** */ /** * キー入力バッファからデータを取得 * @param void : None * @return UCHAR : ==KEY_NONE: キー入力データなし<BR> * : !=KEY_NONE: キー入力データ */ /** ************************************************************** */ UCHAR Key_DatGet( void ) { UCHAR ucDat; ///< キーデータ /** キー入力データがない場合 *********************************/ if ( GKeyCtrlInf.ucWp == GKeyCtrlInf.ucRp ){ ///< キー入力データなし? ucDat = KEY_NONE; ///< キー入力データなし } /** キー入力データがある場合 *********************************/ else { ///<キー入力データあり時
///キー入力データを取得
/// 割込み禁止
/// 位置を更新
/// 割込み許可 ucDat = GKeyCtrlInf.ucBuff[GKeyCtrlInf.ucRp]; __disable_irq(); GKeyCtrlInf.ucRp++; GKeyCtrlInf.ucRp = ( GKeyCtrlInf.ucRp >= KEY_BUFF_SIZE )? 0 : GKeyCtrlInf.ucRp; __enable_irq(); } return( ucDat ); /// キーデータを返す } /** **** ファイルの最後 ( key_ctrl.c ) ************************** */
///key_ctrl.h (キー制御用ヘッダファイル)
/** *********************************************** */ /** * @file key_ctrl.h * @brief キー入力制御用ヘッダファイル * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE */ /** *********************************************** */ #ifndef KEY_CTRL_H ///< KEY_CTRL_H 未定義? #define KEY_CTRL_H ///< KEY_CTRL_H 定義済み!! /* *************************************************************** */ // 定数値の定義 /* *************************************************************** */ /// KEY1 ON/OFF確認
#define KEY1_IN() ( InGPIOBitR(PORT_KEY1,BIT_KEY1)) #define KEY1SFT ( 13 ) ///< KEY1 左シフト数
/// キー長押し時間(5ms * 400 = 2.0 #define TIM_KEY_LONG ( 400 ) s
/// チャタリング除去カウンタ値(5ms単位)*2 =10ms #define KEY_CHATTER_REMOVE_TIM_CNT ( 2 ) /// キー入力コードの定数 #define KEY_NONE (0x00 ) ///< キー入力データなし #define KEY_OFF (0x80 ) ///< キーOFF
#define KEY1_SET (0x01 ) ///< KEY1 設定コード #define KEY1_ON (0x01 ) ///< キー1ON #define KEY1_OFF ( KEY1_ON | KEY_OFF ) ///< キー1OFF /// キー入力コード(長押し/短押し)の定数 #define KEY_LONG (0x20 ) ///< キー長押し #define KEY1_LONG ( KEY_LONG | KEY1_ON ) ///< キー1長押し検出 #define KEY_SHORT (0x40 ) ///< キー短押し #define KEY1_SHORT ( KEY_SHORT | KEY1_ON )///< キー1短押し検出 /// キー入力ステートの定数 #define KEYS_IDLE (0 ) ///< キー入力状態 変化待ち #define KEYS_CHG (1 ) ///< キー入力状態 変化 ///キー入力処理用定数 #define KEY_BUFF_SIZE (10 ) ///< キー入力リングバッファ サイズ /** ************************************************************** */ /** 構造体の定義 */ /** ************************************************************** */ ///キー入力制御情報 構造体の定義 typedef struct { /// キー入力状態 ********************************************* UCHAR ucState; ///< キー入力ステート UCHAR ucInp; ///< キー入力状態 UCHAR ucPrev; ///< キー入力状態(前回) UCHAR ucFix; ///< キー入力状態(確定) UCHAR ucTimCnt;///< チャタリング除去用カウンタ UCHAR ucBuff[KEY_BUFF_SIZE]; ///< キー入力バッファ UCHAR ucWp; ///< ライト位置
UCHAR ucRp; ///< リード位置 USHORT Key1_OnTimCnt; ///< キー1 ON時間カウント(5ms) bool key1_LongWatchEna; ///< キー1長押し監視許可 bool eKey1_Det; ///< キー1長押し } TKeyCtrlInf; /** ******************************************************* */ /** 外部変数の定義 */ /** ******************************************************* */ extern volatile TKeyCtrlInf GKeyCtrlInf; ///< キー入力制御情報 構造体変数宣言 /** ****************************************************** */ /** 関数のプロトタイプ宣言 */ /** ****************************************************** */ extern void Key_Init( void ); ///< キー入力情報の初期化 extern void Key_Input( void );///< キー入力制御 extern UCHAR Key_Proc( void ); ///< キー入力データの取得 #endif /** **** ファイルの最後 ( key_ctrl.h ) ************************** */
///printf.c (出力デバック確認用ファイル)
/** ****************************** */ /** * @file printf.c * @brief printfを使用可能とする。 * @brief Compiler : CubeIDE * @brief CPU : STM32F401 * @date $LastChangedDate: 2023/03/04 $ * @version $Revision : 1.00 $ */ /** ******************************* */ /* ********************************* */ // インクルード ファイル /* ********************************* */ #include "printf.h" /** ******************************* */ // 外部定義変数
/** ******************************* */ ///UART2を使用 extern UART_HandleTypeDef huart2; /** ******************************** */ /** * 説明 * @param 引数(ucInitReq) : UARTを使用して、文字を送信する * @param int c : 出力文字 * @return void : None */ /** ******************************** */ int __io_putchar(int c) { if( c == '\n' ) { int b = '\r'; HAL_UART_Transmit(&huart2,(uint8_t*)&b, 1, 1); } HAL_UART_Transmit(&huart2,(uint8_t*)&c, 1, 1); return 0; } /* setbuf(stdout,NULL); をメイン関数に記載すること。 */ /* ** ファイルの最後 ( printf.c ) ** */
///printf.h (出力デバック用ヘッダファイル)
/** ****************************** */ /** * @file printf.h * @brief printfを使用可能とする。 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE * @date $LastChangedDate : 2023/03/04 $ * */ /** ****************************** */ #ifndef PRINTF_H ///<PRINTF_H 未定義? #define PRINTF_H ///<PRINTF_H 定義済み!! /** ****************************** */ /* インクルード ファイル */ /** ****************************** */ #include "main.h" #include "stdio.h" #endif ///<PRINTF_H 未定義 End /* **** ファイルの最後 ( form.h ) ****************** */
///typedef.h (基本型ヘッダファイル)
/** *********************************************** */ /** * @file typedef.h * @brief 基本型変数定義 * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE */ /** *********************************************** */ #ifndef TYPEDEF_H #define TYPEDEF_H /** * \defgroup CompileOption #ifのコンパイルオプション用 */ /*@{*/ #undef Disable #define Disable 0xffff ///<使用しない場合に指定 /*@}*/ ///BOOL型 #undef false #undef true typedef enum{false=0 ///<為 ,true ///<真 }bool; ///ONOFF型 typedef enum{OFF=0 ///<OFF指定 ,ON ///<ON指定 }ONOFF; ///SIGNAL型 typedef enum{LOW=0 ///<信号をLOWにする ,HIGH ///<信号をHIGHにする。 }SIGNAL; ///UPDOWN型 typedef enum{UP=0 ///<UP指定 ,DOWN ///<DOWN指定 }UPDOWN; ///基本型定義 typedef signed char SCHAR; ///<8bit変数 符号有り typedef unsigned char UCHAR; ///<8bit変数 符号無し typedef signed short SSHORT; ///<16bit変数 符号有り typedef unsigned short USHORT; ///<16bit変数 符号無し #endif
///STMSys.h (STM32レジスタ設定ファイル)
/** *********************************************** */
/** * @file STMSys.h * @brief STM32 基本制御ルーチン * @brief Compiler : CubeIDE * @brief CPU : STM32F401RE */ /** *********************************************** */ #ifndef STMSYS_H #define STMSYS_H /* *************************************************************** */ /** STMSys Settings Define. */ /* *************************************************************** */ #include "main.h" ///< メイン処理制御 /* *************************************************************** */ /** STM32 GPIO Control Define. */ /* *************************************************************** */ ///BIT指定のGPIO出力 ///base:GPIOのベース pin:ピンBIT data:0=OFF/1=ON #define OutGPIOBit(port,pin,data) (port->ODR=((port->ODR&~(pin))|((data==0) ? 0 : (pin)))) ///BIT指定のGPIO出力(反転) ///base:GPIOのベース pin:ピンBIT data:0=OFF/1=ON #define OutGPIOBitR(port,pin,data) (port->ODR=((port->ODR&~(pin))|(data==0) ? (pin) : 0)))
///base:GPIOのベース pin:ピンBIT指定 戻り:0/1
#define InGPIOBitR(port,pin) ((((port->IDR)&(pin))==0)?0:1)
///BIT指定のGPIO入力(反転) ///base:GPIOのベース pin:ピンBIT指定 戻り:0/1 #define InGPIOBitR(port,pin) ((((port->IDR)&(pin))==0)?1:0) #endif
(4) プログラムの説明(キー入力)
GKeyCtrlInf.ucInp |= (ucKey1 & BIT_KEY1 )? KEY1_SET : KEY_NONE;
ucFix :GKeyCtrlInf.ucFix →現在のボタンの確定している状態を表す。
ucInp :GKeyCtrlInf.ucInp →今のボタンを読み込んだ状態を表す。
ucPrev :GKeyCtrlInf.ucPrev →1回前に関数が実行された時のボタンの状態を表す。
BIT_KEY1 :0x01<<13
KEY1_SET :0x01
ucFixが0 :KEY入力無し
ucFixがKEY1_SET:KEY1が押されている状態
(i)if ( GKeyCtrlInf.ucFix & KEY1_SET ) { ///< KEY1 ON時
if ( GKeyCtrlInf.Key1_OnTimCnt < 0xffff ) {
3.関連記事
・STM32マイコン_2(UART通信:TeraTermにHellow表示) - Project_OKI’s diary
・STM32マイコン_3(UART通信:複数文字送信) - Project_OKI’s diary
・STM32マイコン_4(NVICの設定内容) - Project_OKI’s diary
・STM32マイコン_5(スイッチ入力とLED点灯、消灯) - Project_OKI’s diary
その他:
・CubeIDEの使い方(起動~デバック実行) - Project_OKI’s diary
C言語:
・組み込みの為のC言語基礎知識1(printf) - Project_OKI’s diary
・C言語基礎知識2(for分で処理を繰り返す) - Project_OKI’s diary
・C言語基礎知識3(配列) - Project_OKI’s diary