Project_OKI’s diary

エンジニアの勉強ブログ

STM32マイコン30(AD変換と移動平均)

STM32 (AD変換と移動平均)

1.本日の内容

 (1) STM32マイコン(nucleof401re)を使用して、

   スイッチの長押し/短押しの判定を行う。

 

・目次

 

2.内容

(1) やる内容の詳細

 ・nucleof401REでAD変換を行う。

 ・AD変換を行う場合、全ての値を読み取ると、バラツキが大きく、誤差変動が大きくなる。

  そのため、移動平均処理を行い、

  AD変換10データの平均を出し、その値を出力する。

 ・最初にIDLEモードで起動しLEDを点灯

 ・スイッチ(青ボタン)を押すと、MODE1に遷移し、

  LEDを消灯、AD変換を開始、その値をTeraTermに出力する。

 

(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

 ・ AD変換をDMAで行う設定を行う。

 

 CubeIDEの設定については下記を参考

 ・STM32マイコン24(DMAでAD変換) - Project_OKI’s diary

  (今回は連続でAD変換するので、DMAはCircuitモードで行う)

 

(3) プログラムの作成

 今回は、下記ファイルを作成する。

 ・AD変換作成用ファイル    :adc_api.c/adc_api.h

  →新規追加

  → 参考:STM32マイコン24(DMAでAD変換) - Project_OKI’s diary

 

 ・割り込み作成用ファイル  :IntR.c/IntR.h

 ・メイン処理作成用ファイル :self_main.c/self_main.h

  →STM32マイコン27(スイッチの短押し/長押し処理 )の記事のプログラムを一部修正

 

 ・メイン処理ファイル(自動生成):main.c/main.h

 ・stm32f4xx_it.c (割り込みについて記載)

 ・キー制御用ファイル    :key_ctrl.c/key_ctrl.h

 ・led制御用ファイル     :led.c/led.h

 ・printf用ファイル      :printf.c/printf.h

 ・基本型設定用ファイル   :typedef.h

 ・STM32レジスタ設定ファイル:STMSys.h

  →STM32マイコン27(スイッチの短押し/長押し処理 ) と同じ

 

 

///adc_api.c

/** *********************************************** */
/**
 *	@file		IntR.c
 *	@brief		割り込み制御ルーチン群
 *	@brief		Compiler 		: CubeIDE
 *	@brief		CPU			: STM32F401RE
 *	@date		$LastChangedDate	: 2023/04/16  $
 *	@version	$Revision		: 1.00 $
 */
/** *********************************************** */


/** *********************************************** */
/**		インクルードファイル		  */
/** *********************************************** */
#include "typedef.h"	///< 基本型
#include "self_main.h"	///< システム
#include "adc_api.h"	///< ADC制御
#include "main.h"	///< メイン処理

/** *********************************************** */
/**		外部定義変数								*/
/** *********************************************** */

/** *********************************************** */
/**		内部定義変数								*/
/** *********************************************** */

/**	BATT-AD情報 **************************************** */
volatile TAdBattInf 	GAdBattInf;	///< BATT-AD情報

/**	DMA(BATT-AD) **************************************** */
volatile USHORT		GBattDatBuf[1];	///< ADデータ格納バッファ
extern ADC_HandleTypeDef hadc1;

/** *********************************************** */
/**
 *	AD情報の初期化
 *	@param		void			: None
 *	@return		void			: None
 */
/** *********************************************** */
void		AdcApi_BattAdInfInit( void )
{
	USHORT		usCnt;	///< ループカウンタ
	GAdBattInf.eState = AD_ST_STOP;	///< AD変換停止中
	GAdBattInf.bAdFin = false;	///< AD変換完了フラグOFF
	GAdBattInf.usAd = 0;		///< AD値初期化
	GAdBattInf.bWatchReq = false;	///< BATT監視要求フラグOFF

	/** 移動平均制御情報の初期化 ********************************* */
                        /// データ数分のループ for( usCnt=0; usCnt < AD_BATT_MAVE_NUM_DAT; usCnt++ ) { GAdBattInf.usMAveBuf[usCnt] = 0; ///< 移動平均バッファをクリア } GAdBattInf.usWp = 0; ///< 書き込み位置 GAdBattInf.usNumDat = 0;///< データ数 } /** *********************************************** */ /** * BATT-AD AD変換開始 * @param void : None * @return void : None */ /** *********************************************** */ void AdcApi_BattAdStart( void ) { GAdBattInf.eState = AD_ST_STOP; ///< AD変換停止中 GAdBattInf.bAdFin = false; ///< AD変換完了フラグOFF ///ADC DMA転送停止と開始 HAL_ADC_Stop_DMA(&hadc1); ///< ADC DMA転送停止
                         /// ADC DMA転送開始
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)GBattDatBuf, 2); GAdBattInf.eState = AD_ST_RUN; ///< AD変換中(開始) } /** *********************************************** */ /** * BATT-AD AD変換開始チェック(20ms毎) * @param void : None * @return void : None */ /** *********************************************** */ void AdcApi_BattAdChkReStart( void ) { if ( GAdBattInf.eState == AD_ST_RUN ) { ///< AD変換中 if ( GAdBattInf.bAdFin == true ) {///< AD変換完了フラグON? GAdBattInf.bAdFin = false;///< AD変換完了フラグOFF ///ADC DMA転送停止 HAL_ADC_Stop_DMA(&hadc1); ///ADC DMA転送開始 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)GBattDatBuf, 1); } } } /** *********************************************** */ /** * DMA 転送完了割込み処理 * @param ADC_HandleTypeDef : hadc * @return void : None */ /** *********************************************** */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { USHORT ad; if(hadc == &hadc1){ ad = GBattDatBuf[0]; AdcApi_BattAdInt(ad); ///< AD1 電圧の保存 } } /** *********************************************** */ /** * BATT-AD AD変換完了割込み(20ms毎) * @param void : None * @return void : None */ /** *********************************************** */ void AdcApi_BattAdInt( USHORT usAd ) { if ( GAdBattInf.eState == AD_ST_RUN ) { ///< AD変換中 GAdBattInf.usAd = usAd; ///< AD値を更新 /// AD値を移動平均バッファに格納 GAdBattInf.usMAveBuf[GAdBattInf.usWp] = GAdBattInf.usAd; /// バッファの最後の時 if ( GAdBattInf.usWp >= (AD_BATT_MAVE_NUM_DAT-1) ) { GAdBattInf.usWp = 0; ///< 書き込み位置を先頭へ GAdBattInf.bWatchReq = true;///< BATT監視要求フラグON } else { ///< バッファの最後でない GAdBattInf.usWp++; ///< 書き込み位置を更新 } /// データ数更新 GAdBattInf.usNumDat = ( GAdBattInf.usNumDat < AD_BATT_MAVE_NUM_DAT )?(GAdBattInf.usNumDat+1) : AD_BATT_MAVE_NUM_DAT; } GAdBattInf.bAdFin = true; ///< AD変換完了フラグON } /** *********************************************** */ /** * BATT-AD 移動平均値の取得 * @param void : None * @return USHORT : 移動平均値(1秒間) */ /** *********************************************** */ USHORT AdcApi_BattAdGetMoveAve( void ) { USHORT usCnt; ///< ループカウンタ USHORT usNumDat; ///< データ数 USHORT usMAve; ///< 移動平均値 usNumDat = GAdBattInf.usNumDat; ///< データ数を取得 usMAve = 0; ///< 移動平均値をクリア for( usCnt=0; usCnt < usNumDat; usCnt++ ) { ///< データ数分のループ usMAve += GAdBattInf.usMAveBuf[usCnt]; ///< バッファの値を加算 } if ( usNumDat == 0 ) { ///< データ数が0の時 usMAve = 0; ///< 移動平均値=0 } else { ///< データ数が0でない時 usMAve = ( usMAve / usNumDat ); ///< 移動平均値を更新 } return( usMAve ); ///< 移動平均値を返す } /** *********************************************** */ /** * AD監視要求の取得 * @param void : None * @return bool : BATT監視要求 */ /** *********************************************** */ bool AdcApi_GetWatchReq( void ) { return( GAdBattInf.bWatchReq ); ///< BATT監視要求を返す } /** *********************************************** */ /** * AD監視要求の設定 * @param bool : BATT監視要求 * @return void : None */ /** *********************************************** */ void AdcApi_SetWatchReq( bool bWatchReq ) { GAdBattInf.bWatchReq = bWatchReq; ///< BATT監視要求を設定 } /** *** ファイルの最後 ( adc_api.c ) ***************************** */

 

///adc_api.h

/** *********************************************** */
/**
 *	@file		IntR.c
 *	@brief		割り込み制御ルーチン群
 *	@brief		Compiler 		: CubeIDE
 *	@brief		CPU			: STM32F401RE
 *	@date		$LastChangedDate	: 2023/04/16  $
 *	@version	$Revision		: 1.00 $
 */
/** *********************************************** */

#ifndef		ADC_API_H	///< ADC_API_H 未定義?
#define		ADC_API_H	///< ADC_API_H 定義済み!!

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

/** *********************************************** */
/**	\defgroup ADCAPI_DEF ADC制御API処理用の定義 */
/** *********************************************** */
/*@{*/
#define		MAX_AD_VAL		(4095 )	///< AD変換最大値(10ビット)
#define		MAX_AD_VOLT		(3000 )	///< AD変換最大電圧値[mV]
/*@}*/

/** *********************************************** */
/**	\defgroup ADC1SEQ0_DEF ADC1SEQ0(BATT)用の定義*/
/** *********************************************** */
/*@{*/
#define		AD_BATT_NUM_CH		(2)///< AD変換チャネル
#define		AD_BATT_MAVE_NUM_DAT	(10)///< 移動平均データ数
#define		AD_TIM_CNT		(4)///< AD変換周期(5ms単位:5ms*4=20ms)
/*@}*/

/** *********************************************** */
/**		列挙型の定義			  */
/** *********************************************** */
/** *********************************************** */
/**
 *	\defgroup AD_STATE AD動作ステートの定義
*/
/** *********************************************** */
/*@{*/
/**	動作ステートの定義 ************************************** */
typedef enum {
	AD_ST_STOP=0,		///< AD変換停止中ステート
	AD_ST_RUN		///< AD変換中ステート
} TAD_ST;
/*@}*/

/** *********************************************** */
/**		構造体の定義								*/
/** *********************************************** */
/** *********************************************** */
/**		ADC1用 構造体の定義							*/
/** *********************************************** */
typedef struct {
	TAD_ST		eState;	///< 動作ステート
	bool		bAdFin;	///< AD変換完了フラグ(true:ON)
	USHORT		usAd;	///< AD値
	bool		bWatchReq;	///< BATT監視要求フラグ
	bool		bWatchAcAdapterReq;///< ACアダプタ状態監視要求フラグ
	USHORT		usMAveBuf[AD_BATT_MAVE_NUM_DAT];///< 移動平均バッファ
	USHORT		usWp;		///< 書き込み位置
	USHORT		usNumDat;	///< データ数
} TAdBattInf;

/** *********************************************** */
/**		外部変数の定義								*/
/** *********************************************** */
/**	AD1情報 **************************************** */
extern volatile TAdBattInf	GAdBattInf;	///< ADC1情報

/** *********************************************** */
/**		関数のプロトタイプ宣言						*/
/** *********************************************** */
extern void	AdcApi_BattAdInfInit( void );	///< AD情報の初期化
extern void	AdcApi_BattAdStart( void );	///< AD変換開始(初回用)
extern void	AdcApi_BattAdChkReStart( void );///< AD変換開始チェック(20ms毎)
extern void	AdcApi_BattAdInt( USHORT usAd );///< AD変換完了割込み(20ms毎)
extern USHORT	AdcApi_BattAdGetMoveAve( void );///< AD移動平均値(1秒間)の取得
extern bool	AdcApi_GetWatchReq( void );	///< AD監視要求の取得
extern void	AdcApi_SetWatchReq( bool bWatchReq );///< AD監視要求の設定
#endif


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

 

///self_main.c (メイン処理、main.cとは別に、自分で書き換えやすいように作成)

/** *********************************************** */
/**
 *	@file		self_main.c
 *	@brief		メイン処理
 *	@brief		Compiler 		: CubeIDE
 *	@brief		CPU			: STM32F401RE
 *	@brief		変更内容		: AD変換追加
 *	@date		$LastChangedDate	: 2023/03/21  $
 */
/** *********************************************** */


/**	************************************************************** */
/*		インクルード ファイル				*/
/**	************************************************************** */
#include	<stddef.h>				///< 標準定義
#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制御
#include	"adc_api.h"				///< adc制御

/**	************************************************************** */
/*		外部定義変数					*/
/**	************************************************************** */
volatile TSysCtrlInf		GSysCtrlInf;	///< システム制御情報
volatile TKeyCtrlInf		GKeyCtrlInf;	///< キー制御情報

/**	************************************************************** */
/*		内部関数のプロトタイプ宣言			*/
/**	************************************************************** */
void SysInit(void);		///<システム初期化
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();
	///AD変換情報初期化
	AdcApi_BattAdInfInit();
}

#if 1
/**	************************************ */
/**
 *	メインループ
 *	@param		void			: None
 *	@return		void			: None
 */
/**	************************************ */
void	MainLoop( void )
{
	///キー監視開始
	GKeyCtrlInf.key1_LongWatchEna = true;
	///AD変換開始
	AdcApi_BattAdStart();

	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; ///< キー入力 USHORT adValue; ///< 取得平均AD値 USHORT battValue; ///< 取得電圧値[mV] Led1(LOW); ///< LED1消灯 ///AD変換処理 if(GAdBattInf.bWatchReq == true){ ///< AD変換値出力許可フラグON時 GAdBattInf.bWatchReq = false; ///< AD変換値出力許可フラグOFF adValue = AdcApi_BattAdGetMoveAve();///< 平均AD値の取得 battValue = adValue*MAX_AD_VOLT/MAX_AD_VAL;///< 取得電圧値[mV] printf("battValue = %d[mV]\n",battValue); ///< 取得した電圧値を表示 } 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; ///< キー入力 GLEDCTRL.led1blif=true; ///< LED点滅フラグON(LED点滅開始) ucKey = Key_Proc(); ///< キー入力確認 printf("LCD_Rev_Proc:ucKey=%d\n",ucKey);///< 入力キーを表示 if(ucKey == KEY1_SHORT){ ///< KEY1短押し時 GLEDCTRL.led1blif=false; ///< LED点滅フラグOFF GSysCtrlInf.eNMode = INIT; ///< IDLEモードへ遷移 }else if(ucKey == KEY1_LONG){ ///< KEY1長押し時 GLEDCTRL.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

/** *********************************************** */
/*		System Settings Define.		    */
/** *********************************************** */

//LED GPIO
#define PORT_LED1		LED1_GPIO_Port	
#define BIT_LED1		LED1_Pin 				

///入力キー
#define PORT_KEY1		KEY1_GPIO_Port						
#define BIT_KEY1		KEY1_Pin		

#define PORT_KEY2		KEY2_GPIO_Port						
#define BIT_KEY2		KEY2_Pin		

#define PORT_KEY3		KEY3_GPIO_Port						
#define BIT_KEY3		KEY3_Pin

/**	************************************************************** */
/**		列挙型の定義					*/
/**	************************************************************** */

//メイン動作モード
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		SysInit(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  $
 *	@version	$Revision		: 1.00 $
 */
/** *********************************************** */

#include <stddef.h>
#include "typedef.h"		///< 基本型
#include "STMLib/STMSys.h"	///< STMLib用
#include "key_ctrl.h"		///< キー入力制御
#include "IntR.h"		///< 割り込み制御
#include "main.h"		///< メイン処理
#include "self_main.h"		///< selfメイン処理
#include "adc_api.h"		///< AD変換制御
#include "led.h"		///< led制御
#include "printf.h"		///< printf制御

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

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

	/// 5ms時実行
	if(GTimCtrlInf.uc5msCnt >= TIM5MS_CNT_VAL){
		GTimCtrlInf.uc5msCnt = 0;	///<5msカウンタ初期化
		Key_Input();				///<キー入力制御
	}

	///20ms時実行(追加) 
	if(GTimCtrlInf.uc20msCnt >= TIM20MS_CNT_VAL){
		GTimCtrlInf.uc20msCnt = 0;	///< 20msカウンタ初期化
		AdcApi_BattAdChkReStart();	///< AD変換開始処理
	}

	///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  $
 *	@version	$Revision		: 1.00 $
 */
/** *********************************************** */

#ifndef INTR_H
#define INTR_H

/**	100msタイマ値(5ms単位)用の定義 ******************************* */
#define		TIM5MS_CNT_VAL	(5)///< 5msタイマ値(1ms*5=5ms)
/**	20msタイマ値(5ms単位)用の定義 ******************************* */
#define		TIM20MS_CNT_VAL	(20)///< 20msタイマ値(1ms*20=20ms)
/**	1sタイマ値(100ms単位)用の定義 ******************************** */
#define		TIM1S_CNT_VAL	(1000)	///< 1sタイマ値(1ms*1000=1s)

/** *********************************************** */
/*		構造体の定義		   */
/** *********************************************** */
///	タイマ制御情報 構造体の定義
typedef struct {
	/**	タイマ制御情報 ******************************************* */
	UCHAR			ucState;	///< 動作ステート
	UCHAR			uc5msCnt;	///< 5msカウンタ
	UCHAR			uc20msCnt;	///< 20msカウンタ
	UCHAR			uc100msCnt;	///< 100msカウンタ
	UINT			uc1sCnt;	///< 1s カウンタ
} TTimCtrlInf;

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

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

#endif

 

 

(4) プログラムの説明(AD変換)
 (a) AdcApi_BattAdInfInit
   AD変換に使用するTAdBattInf構造体の初期化を行う。
 (b) AdcApi_BattAdStart
    AD変換の開始を行う関数。
   メイン処理で実行され、この処理が実行されるとAD変換を開始する。
 (c) AdcApi_BattAdChkReStart
   割り込み処理で20ms毎に実行する。
  AD変換を行うフラグを確認し、AD変換中の場合、AD変換を開始する。
 (d) AdcApi_BattAdInt
  AD変換完了割り込み時(HAL_ADC_ConvCpltCallback)に、実行する。
  AD変換結果をバッファに格納し、保持する。
  AD変換値が10個溜まったら、AD移動平均処理を許可し、AD変換を格納するバッファのバッファ位置を0に戻す。
 (e) AdcApi_BattAdGetMoveAve
  AD移動平均値の取得を行う関数。
  AD変換出力許可フラグがtrueになった時実行される。
  AD変換値を格納しているバッファの値を全て足し、
  それをデータ数で割ることにより、移動平均値を算出する。
  AD変換のデータ数が0だとエラーになるため、
  0の場合は割り算が起こらないようにしている。
  AD移動平均値を返しす。
 
 (f) HAL_ADC_ConvCpltCallback
 AD変換が終了した時に自動的に呼び出されるHALで用意された割り込み関数
 AD変換が終ったらGBattDatBuf[0]の値を読み込み、
 それをAD変換値格納バッファに格納している。
 
 

3.関連記事

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