Project_OKI’s diary

エンジニアの勉強ブログ

STM32マイコン26(割り込み:TIM3_IRQHandler)

 

割り込み:TIM3_IRQHandler

1.本日の内容

 (1) STM32マイコン(nucleof401RE)を使用しLEDの点灯/消灯を制御する。

 (2) 割り込み処理を行う場合、下記2つの関数がある。

  ・void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

  ・void TIM3_IRQHandler(void)

  TIM3_IRQHandlerの使い方と、2つの関数の違いについて説明する。

 

 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

 の実装方法などは下記を参照

 ・STM32マイコン20(割り込み処理部分を別ファイルに作成) - Project_OKI’s diary

 ・STM32マイコン_9(タイマ割り込み:LED点滅) - Project_OKI’s diary

 

・目次

 

2.内容

​​(1) やる内容の詳細​

 ・void TIM3_IRQHandler(void)を使用し、割り込み処理を実装する。

 ・割り込み処理によって、LEDを1秒ごとに点灯/消灯を繰り返す。

 ・TIM3_IRQHandlerHAL_TIM_PeriodElapsedCallbackの違いについて説明する。

  (メリットデメリットなど)

 

(2) CubeMXの設定

 CubeMXの設定は、下記記事と同じ。

 →STM32マイコン_9(タイマ割り込み:LED点滅) - Project_OKI’s diary

 

(3) プログラムの作成

typedef.hファイルの作成

/**
*	@file		typedef.h
*	@brief		基本型変数定義
*/

#ifndef TYPEDEF_H
#define TYPEDEF_H

///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;

///基本型定義
typedef signed char	SCHAR;		///<8bit変数 符号有り
typedef unsigned char	UCHAR;		///<8bit変数 符号無し
typedef signed short	SSHORT;		///<16bit変数 符号有り
typedef unsigned short	USHORT;		///<16bit変数 符号無し
typedef signed int	SINT;		///<int型 符号有り(8bitサイズ)
typedef unsigned int	UINT;		///<int型 符号無し(8bitサイズ)
typedef signed long	SLONG;		///<32bit変数 符号有り
typedef unsigned long	ULONG;		///<32bit変数 符号無し

#endif

 

led.cファイルの作成

/**	******************************************************* */
/**
 *	@file		led.c
 *	@brief		LED制御処理
 *	@brief		Compiler 	: Atollic True Studio for STM32 9.0.0
 *	@brief		CPU			: STM32F401
 */
/**	******************************************************* */

/* ************************************************************ */
//		インクルード ファイル																			
/* ************************************************************* */
#include "main.h"
#include "led.h"    	//LED制御ヘッダファイルのインクルード

/** ************************************************************ */
/**		外部定義変数																						*/
/** ************************************************************ */
	LEDCTRL 		ledctrl;   //LED制御構造体

/** ******************************************************* */
//		関数の作成																						
/** *************************************************** */

/**	*********************************************** */
/**
*	MODE1 LED点灯/消灯処理(LED1を点灯/消灯(反転)する処理)
*	@param	void        	: none
*	@return	void		: none
*/ /** ************************************************ */ void Led1Blink() { ///LED点滅フラグ確認 if(ledctrl.led1blif == true){ if(Led1State == HIGH){ ///LEDがHIGHの時 Led1(LOW); ///LED1をON }else{ ///LED1がLOWの時 Led1(HIGH); ///LED1をOFF } } } /* **** ファイルの最後 ( led.c ) ******************************** */

 

led.hファイルの作成

/**	******************************************** */
/**
 *	@file		led.h
 *	@brief		LED制御ヘッダ
 *	@brief		Compiler 	: Atollic True Studio for STM32 9.0.0
 *	@brief		CPU			: STM32F401RE
 *
 */
/**	******************************************** */

///多重インクルード防止
#ifndef LED_H ///<LED未定義?
#define LED_H ///<LED_H 定義済み!!

/* ****************************************************** */
//		インクルード ファイル																			
/**************************************************** */
#include "typedef.h"	//基本型変数定義ヘッダファイルのインクルード

/* **************************************************** */
//		定数値の定義																					
/* **************************************************** */

/* ************************************************** */
//		式、関数の置き換え																						
/* **************************************************** */
///Bit変換:出力
#define OutGPIOBit(port,pin,data)	(port->ODR=((port->ODR&~(pin))|((data==0) ? 0 : (pin))))	///GPIO設定
///Bit変換:入力
#define InGPIO(port,pin) ((((port->IDR)&(pin))==0)?0:1)

///LED ON/OFF関数の作成
#define Led1(dt)	OutGPIOBit(LED1_GPIO_Port,LED1_Pin,dt)
///LEDステート確認用変数
#define Led1State	InGPIO(LED1_GPIO_Port,LED1_Pin)					

/* ****************************************************** */
//	構造体の定義																					
/* ************************************************ */
//MODE LEDステート管理用構造体
typedef struct{
	//LED動作ステート
	USHORT		led1blicout;///LED点滅時間カウント用変数
	bool		led1blif;   ///LED1点滅ステート:true:LED点滅 false:LED点滅しない
} LEDCTRL;

/* **************************************************** */
//		外部変数の定義																					
/* ********************************************* */
extern LEDCTRL 		ledctrl;	///LED制御構造体

/* ********************************************** */
//	関数のプロトタイプ宣言																				
/* ********************************************* */
extern void Led1Blink();	///LED1を点灯/消灯(反転)関数

#endif ///<LED_H 未定義 End

/* **** ファイルの最後 ( led.h ) ************************* */

 

main.cファイルの作成

/* USER CODE BEGIN Includes */
#include "typedef.h"
#include "led.h"
/* USER CODE END Includes */
  /* USER CODE BEGIN 2 */
  //TIM3開始
  HAL_TIM_Base_Start_IT(&htim3);

  //LED点滅開始
  ledctrl.led1blif = true;

  /* USER CODE END 2 */

 

stm32f4xx_it.cファイル (割り込みについて記載、CubeMXで自動生成される。)

ここに、TIM3_IRQHandlerが自動的に作成される。

TIM3_IRQHandlerのUSER CODEに自分が作成した割り込みの関数などを実行する。

/* 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 */

 

IntR.cファイルの作成

/** *********************************************** */
/** 
 *	@file		IntR.c
 *	@brief		割り込み制御
 *	@brief		Compiler 		: CubeIDE
 *	@brief		CPU			: STM32F401RE
 */
/** *********************************************** */

#include "typedef.h"		///< 基本型
#include "IntR.h"		///< 割り込み制御
#include "main.h"		///< メイン処理
#include "led.h"		///< led制御

/**************************************************************** */
/**          グローバル変数定義                                   */
/**************************************************************** */
///構造体宣言
volatile TTimCtrlInf		GTimCtrlInf;
///ハンドラ宣言
extern TIM_HandleTypeDef htim3;

/* *************************************************************** */
/**		STM32 関数作成				          */
/* *************************************************************** */

/**	************************************************************** */
/**
 *	TIM3割り込み処理(1msごとに割り込み)
 *	@param		void			: None
 *	@return		void			: None
 */
/**	************************************************************** */
void Tim3_Int()
{
	///1ms経過毎の処理
	GTimCtrlInf.uc1sCnt++;		///< 1sカウンタを更新

	///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	TIM1S_CNT_VAL	1000  ///< 1sタイマ値(1ms*1000=1s)

/** *********************************************** */
/*		構造体の定義			    */
/** *********************************************** */
///	タイマ制御情報 構造体の定義
typedef struct {
	UINT	uc1sCnt;///< 1s カウンタ
} TTimCtrlInf;

/** *********************************************** */
/*		外部変数の定義			    */
/** *********************************************** */
extern volatile TTimCtrlInf	GTimCtrlInf;	///< タイマ制御情報

/** *********************************************** */
/*		プロトタイプ宣言		   */
/** *********************************************** */
extern void Tim3_Int();
#endif

 

 

(4) プログラムの説明
 (a) 基本は下記記事と同じ
   を参照
   Led1Blinkは、LEDが点灯してたら、LEDを消灯。
   LEDが消灯していたらLEDを点灯する関数。
 
 (b) #define OutGPIOBit(port,pin,data) (port->ODR=*1|((data==0) ? 0 : (pin)))) ///GPIO設定 
  #define Led1(dt) OutGPIOBit(LED1_GPIO_Port,LED1_Pin,dt)
  これで、レジスタ操作により、LEDのON/OFFを行っている。
 
 (c) HAL_TIM_Base_Start_IT(&htim3);
  TIM3開始関数。これにより、設定した秒数でタイマ割り込みが行われる。
  今回は、tim3を1秒に1回実行している。
 
 (d)  Tim3_Int();
   今回割り込みを行う関数。
   自動生成された、TIM3_IRQHandlerUSER CODE BEGIN TIM3_IRQn 1
   に記載することで、1秒に1回、割り込み処理が実行される。
 
   ledctrl.led1blifをLED点滅フラグを確認し、trueの場合、下記動作を実行する。
   LEDが点灯していたらLEDを消灯
   LEDが消灯していたらLEDを点灯する。
 
  とほぼ同じで、どちらも1秒に1回割り込み処理を実行している。
 
(5) TIM3_IRQHandlerHAL_TIM_PeriodElapsedCallbackの違い
 ・TIM3_IRQHandler
 タイマー3の割り込みハンドラーであり、直接割り込みを処理する関数。
 この関数を使用すると、より低レベルの割り込み処理を実装することができる。
 割り込みハンドラーは、プロセッサが割り込みを受け取った際に、
 直接呼び出されるため、割り込みに対する最速の応答が必要な場合に使用される。
 
HAL_TIM_PeriodElapsedCallback
 HALドライバで呼び出されるコールバック関数。
 割り込み処理が行われると、HALドライバにより自動的に呼び出される。
 割り込みハンドラーの処理が終了した後に呼び出されるため、
 割り込みに対する迅速な応答は必要ない場合に使用される。
 
 使い分けとしては、

 以下の場合は、HALドライバより、TIM3_IRQHandlerに記載した方が良い。

 

  ・割り込みが発生して、すぐにレジスタ値を読み込んで処理をする必要がある場合。(DMAなど)
  ・割り込みが発生した際に直ちにデータを受信する必要がある場合
  ・特定のシリアル通信モードに移行するために特定のレジスタに特定の値を書き込む必要がある場合

それ以外だと基本は、HALドライバを使用した方が、コード変更が容易になり、
他のCPUへの応用もききやすい。

 
 下記記事は、TIM3の処理手順の中身を追っているので、参考になる。
 

3.関連記事

関連記事一覧:
 
組み込みC言語

 

*1:port->ODR&~(pin