STM32CubeMXスタディノート(5)-基本的なタイマーインターフェイスの使用

1.タイマーの紹介

STM32F1シリーズは、インターネットベースの製品に加えて8、基本タイマー、汎用タイマー、高度なタイマーに分けられた合計タイマーです。
基本タイマー TIM6TIM7、16ビットのみ、タイミングのみ、外部IOなしでカウントアップするタイマー。
汎用タイマー TIM2/3/4/5は、カウントアップ/カウントダウンが可能な16ビットタイマーで、計時、出力比較、入力キャプチャが可能です。各タイマーには4つの外部IOがあります。
アドバンストタイマー TIM1/8は、カウントアップ/カウントダウンが可能な16ビットタイマーで、計時、出力比較、入力キャプチャ、および三相モーター相補出力信号が可能です。各タイマーには8つの外部IOがあります。

2.新築

1. STM32CubeMXソフトウェアを開き、[新しいプロジェクト]をクリックします

2.MCUとパッケージを選択します

3.クロック
RCC設定を構成し、 HSE(外部高速クロック)を

選択し、水晶/セラミック共振子(水晶発振器/セラミック共振子)のクロック構成を選択し、システムクロックSYSCLKを72MHzに構成し、
HCLKの値を72に変更します。 Enterキーを押します。すべての構成を自動的に変更します

4.デバッグモード
設定することは非常に重要なステップです
設定しないと、最初のプログラミングプログラムの後でデバッガのSYS設定が認識されません。[シリアルワイヤとしてデバッグ]を選択してください。

5. GPIO
GPIO設定を構成し、右の図でLEDライトの対応するピンを見つけ、GPIO_Outputを選択し、低レベルのライトを出力します。カスタムラベルを追加できます。

3、TIM6基本タイマー

3.1パラメータ設定

設定Timers選択でTIM6Activatedアクティベーションを確認します

Parameter Settings特定のパラメータ。

Tclkは内部クロックCK_INTであり、APB1プリスケーラーで除算されます。APB1プリスケーラー係数が1の場合、周波数は変更されません。それ以外の場合、周波数は2倍され、ライブラリ関数のAPB1プリスケーラー係数は2になります。つまり、図に示すように、PCLK1 = 36M、タイマークロックTclk = 36 * 2 = 72Mです。

タイマーオーバーフロー時間:

すべて= 1 /(Tclk /(psc + 1))∗(arr + 1)

  • タイマークロックTclk:72MHz
  • プリスケーラpsc:71
  • 自動リロードレジスタ到着:999

即 Tout = 1/(72MHz/(71+1))∗(999+1) = 1ms

  • プリスケーラ(クロックプリスケーラ番号):72-1 则驱动计数器的时钟 CK_CNT = CK_INT(即72MHz)/(71+1) = 1MHz
  • カウンターモード:アップ(アップカウントモード) 基本定时器只能是向上计数
  • カウンター期間(自動リロード値):1000-1 则定时时间 1/CK_CLK*(999+1) = 1ms
  • auto-reload-preload(自動リロード):有効(有効) `
  • TRGOパラメーター(トリガー出力):無効 在定时器的定时时间到达的时候输出一个信号(如:定时器更新产生TRGO信号来触发ADC的同步转换)

3.2NVIC構成

タイマー割り込みを有効にする

3.3コードを生成する



アプリケーション開発環境のパスアイテム名とアイテム入力の選択IDEMDK-ARM V5

各ペリフェラルはフックではなく個別の’.c/.h’ファイルを生成します
:すべての初期化コードはmain.cで生成され
ますチェック済み:初期化コードファイルは関連するペリフェラルで生成されます。たとえば、GPIO初期化コードはgpio.cで生成されます。
[コードを生成]をクリックしてコードを生成します

3.4割り込みコールバック関数を変更する

stm32f1xx_it.c割り込みサービスルーチンファイルを開き、TIM6_IRQHandler()
タイマー割り込みハンドラと呼ばれるTIM6割り込みサービスルーチン割り込みサービス関数を見つけます。HAL_TIM_IRQHandler()

stm32f1xx_hal_tim.cファイルを開き、タイマー割り込みハンドラーのプロトタイプを見つけますHAL_TIM_IRQHandler()。その主な役割は、生成されるタイマー割り込みの種類を判別し、割り込みフラグをクリアしてから、割り込みコールバック関数を呼び出すことHAL_TIM_PeriodElapsedCallback()です。

/ *注:この関数は変更しないでください。コールバックが必要な場合は
、HAL_GPIO_EXTI_Callbackをユーザーファイルに実装できます
* /
この関数は変更しないでください。コールバック関数を使用する必要がある場合は、関数を再実装してください。ユーザーファイル内。

HAL_TIM_PeriodElapsedCallback()公式プロンプトによる__weakと、弱められたフラグである関数を再度定義する必要があります。これを持つ関数は弱められた関数です。つまり、他の場所でまったく同じ名前とパラメーターを持つ関数を記述でき、コンパイラーは無視します。この関数。代わりにUNUSED(htim)、作成した関数を実行します。これはエラー防止の定義です。渡されたタイマー番号が処理を行わない場合、コンパイラーは警告を報告しません。実際、開発中に割り込みサービス関数について気にする必要はありません。割り込みコールバック関数を見つけて書き直すだけで済みます。このコールバック関数には、ここには反映されていないもう1つの非常に便利な側面があります。複数の割り込みが有効になっている場合、STM32CubeMXは複数の割り込みのサービス関数を自動的に編成し、コールバック関数を呼び出します。つまり、割り込みの数に関係なく、コールバック関数を書き直して着信タイマー番号を判断するだけで済みます。

次にstm32f1xx_it.c、このドキュメントの最後に追加しますHAL_TIM_PeriodElapsedCallback()

/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
    static uint32_t time = 0;
	if(htim->Instance == TIM6)  // 定时器6基地址
	{
    
    
        // 自定义应用程序
        time++;           // 每1ms进来1次
        if(time == 1000)  // 每1秒LED灯翻转一次
        {
    
    
            HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
            time = 0;
        }
	}
}
/* USER CODE END 1 */

3.5タイマースタート機能の追加

ここで、main関数に入り、whileループの前にタイマー関数を追加しますHAL_TIM_Base_Start_IT()。ここで渡されるhtim6は、タイマーが初期化された直後の構造体です。

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim6);  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

実験的な現象は、LEDライトが1秒に1回点滅することです

3.6HALライブラリと標準ライブラリコードの比較

STM32CubeMXは、HALライブラリによって生成されたコードを使用します。

/**
  * @brief TIM6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM6_Init(void)
{
    
    

  /* USER CODE BEGIN TIM6_Init 0 */

  /* USER CODE END TIM6_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {
    
    0};

  /* USER CODE BEGIN TIM6_Init 1 */

  /* USER CODE END TIM6_Init 1 */
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 72-1;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 1000-1;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */
}

/**
  * @brief This function handles TIM6 global interrupt.
  */
void TIM6_IRQHandler(void)
{
    
    
  /* USER CODE BEGIN TIM6_IRQn 0 */

  /* USER CODE END TIM6_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_IRQn 1 */

  /* USER CODE END TIM6_IRQn 1 */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
    static uint32_t time = 0;
    if(htim->Instance == TIM6)
    {
    
    
        // 自定义应用程序
        time++;
        if(time == 1000)
        {
    
    
            HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
            time = 0;
        }
    }
}

HAL_TIM_Base_Start_IT(&htim6); 

STM32標準ライブラリコードを使用します。

/**
 @brief 定时器中断配置(使用TIM6基本定时器)
 @param 无
 @return 无
*/
void BASIC_TIM_Config(void)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	/*
	可以从上图看出基本定时器和通用定时器使用APB1总线,
	高级定时器使用APB2总线。
	*/
	// 开启定时器时钟,即内部时钟 CK_INT=72M
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

	/*
	预分频将输入时钟频率按1~65536之间的值任意分频,分频值决定了计数频率。
	计数值为计数的个数,当计数寄存器的值达到计数值时,产生溢出,发生中断。
	如系统时钟为72MHz,预分频 TIM_Prescaler = 71,
	计数值 TIM_Period = 1000,
	则 TIM_Period * (TIM_Prescaler + 1) / 72000000 = 0.001,
	即每1ms产生一次中断。
	*/
	// 自动重装载寄存器周的值(计数值)
	TIM_TimeBaseStructure.TIM_Period = 1000;
 
	// 累计 TIM_Period 个频率后产生一个更新或者中断
	// 时钟预分频数为 71,
	// 则驱动计数器的时钟 CK_CNT = CK_INT / (71+1)=1M
	TIM_TimeBaseStructure.TIM_Prescaler = 71;

	// 时钟分频因子 ,基本定时器没有,不用管
	//TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;

	// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
	//TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;

	// 重复计数器的值,基本定时器没有,不用管
	//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;

	/*
	完成时基设置
	*/
	// 初始化定时器
	TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

	/*
	为了避免在设置时进入中断,这里需要清除中断标志位。
	如果是向上计数模式(基本定时器采用向上计数),
	则采用函数 TIM_ClearFlag(TIM6, TIM_FLAG_Update),
	清除向上溢出中断标志。
	*/
	// 清除计数器中断标志位
	TIM_ClearFlag(TIM6, TIM_FLAG_Update);

	// 使能计数器
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);

	// 开启计数器
	TIM_Cmd(TIM6, ENABLE);

	// 暂时关闭定时器的时钟,等待使用
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, DISABLE);
}

/**
 @brief NVIC初始化(使用TIM6基本定时器)
 @param 无
 @return 无
*/
void BASIC_TIM_NVIC_Config(void)
{
    
    
	NVIC_InitTypeDef NVIC_InitStructure;
	// 设置中断组为 0
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	// 设置中断来源
	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn ;
	// 设置主优先级为 0
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	// 设置抢占优先级为 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

#define BASIC_TIM_IRQHandler TIM6_IRQHandler
// 1ms发生一次中断,time 记录中断次数
uint16_t time;

void BASIC_TIM_IRQHandler(void)
{
    
    
	if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
	{
    
    
		time++;
		TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update);
	}
}

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

MX_TIM6_Init();対応BASIC_TIM_Config();BASIC_TIM_NVIC_Config();
HAL_TIM_Base_Init(&htim6)対応TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure)
HAL_TIM_Base_Start_IT(&htim6);対応RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

四、注意が必要な事項

追加するユーザーコードUSER CODE BEGIN NUSER CODE END Nその間に追加するユーザーコード。それ以外の場合は、STM32CubeMXがコードを再生成した後、次に使用すると削除されます。


2021年1月14日にLeungによって書かれました

•リファレンス:STM32CubeMXシリーズチュートリアル3:基本タイマー
    STM32CubeMX実際の戦闘チュートリアル(4)-基本タイマー(まだ点灯)「組み込み-STM32
    開発ガイド」パート2基本-第4章タイマー(HALライブラリ)

おすすめ

転載: blog.csdn.net/qq_36347513/article/details/112599813