STM32CubeMX研究ノート(4)-システムの遅延使用

1.SysTickの紹介

SysTick:システムタイマーはCM3コアの周辺機器であり、NVICに組み込まれています。システムタイマーは24ビットのダウンカウンターです。各カウンターの時刻は1 / SYSCLKです。通常、システムクロックSYSCLK72Mに設定しますリロードされた値レジスタの値が0にデクリメントされると、システムタイマーは割り込みを生成し、割り込みが前後に循環します。

SysTickCM3コアに属する周辺機器であるため、すべてのCM3コアベースのマイクロコントローラーにはこのシステムタイマーがあり、ソフトウェアをCM3マイクロコントローラーに簡単に移植できます。システムタイマーは通常、オペレーティングシステムでタイムベースを生成し、オペレーティングシステムのハートビートを維持するために使用されます。

2.新築

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

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

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

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

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

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

6.生成されたコード
入力パス項目名と

アプリケーション開発環境の項目選択IDEMDK-ARM V5

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

3、通常の遅延

3.1ウォーターランプを実現するためにメイン機能を変更する

追加機能ピンの出力は、while()ループHAL_GPIO_TogglePin()および遅延機能で反転されますHAL_Delay()

/**
  * @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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);

    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

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

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

/**
  * @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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);

    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

HAL_StatusTypeDef HAL_Init(void)
{
    
    
  /* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
    defined(STM32F102x6) || defined(STM32F102xB) || \
    defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
    defined(STM32F105xC) || defined(STM32F107xC)

  /* Prefetch buffer is not available on value line devices */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#endif /* PREFETCH_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);

  /* Init the low level hardware */
  HAL_MspInit();

  /* Return function status */
  return HAL_OK;
}

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
    
    
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    
    
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    
    
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    
    
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
    
    
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

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

/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main(void)
{
    
    	
	/* LED 端口初始化 */
	LED_GPIO_Config();

	/* 配置SysTick 为10us中断一次 */
	SysTick_Init();

	for(;;)
	{
    
    

		LED1( ON ); 
		SysTick_Delay_Ms( 1000 );
		LED1( OFF );
	  
		LED2( ON );
		SysTick_Delay_Ms( 1000 );
		LED2( OFF );
	} 	
}

/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */
void SysTick_Init(void)
{
    
    
	/* SystemFrequency / 1000    1ms中断一次
	 * SystemFrequency / 100000	 10us中断一次
	 * SystemFrequency / 1000000 1us中断一次
	 */
//	if (SysTick_Config(SystemFrequency / 100000))	// ST3.0.0库版本
	if (SysTick_Config(SystemCoreClock / 100000))	// ST3.5.0库版本
	{
    
     
		/* Capture error */ 
		while (1);
	}
}

// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)

void SysTick_Delay_Us( __IO uint32_t us)
{
    
    
	uint32_t i;
	SysTick_Config(SystemCoreClock/1000000);
	
	for(i=0;i<us;i++)
	{
    
    
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1	
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Delay_Ms( __IO uint32_t ms)
{
    
    
	uint32_t i;	
	SysTick_Config(SystemCoreClock/1000);
	
	for(i=0;i<ms;i++)
	{
    
    
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
		// 当置1时,读取该位会清0
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

HAL_InitTick(TICK_INT_PRIORITY);対応SysTick_Init();
HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))対応SysTick_Config(SystemCoreClock/1000000)
HAL_Delay(500);対応SysTick_Delay_Ms(500);

第四に、割り込みの遅延

(3)ESP8266の研究ノート- GPIOインタフェースHAL_GPIO_EXTI_Callbackを追加キーデバウンス

/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if(GPIO_Pin==KEY1_Pin)
	{
    
    
        HAL_Delay(100);
        if(HAL_GPIO_ReadPin(KEY1_Pin_Port,KEY1_Pin)==1)
        {
    
    
            HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
        }
	}
}
/* USER CODE END 1 */

これで、MCUにダウンロードすると、ボタンが押された後にのみ応答がなくなります。これが、実際、問題がHAL_Delay()そこにある理由です。

コールバック関数に入った後HAL_Delay、Systickの優先度が低すぎたため、無限ループに陥りました。

Systick割り込みのプリエンプション優先度は、外部割り込みのプリエンプション優先度と同じです。その後、外部割り込みがトリガーされたときにSystick割り込みをトリガーしないでください。問題が見つかりました。外部割り込みのプリエンプション優先度を下げるだけです。 。

  • 優先度を優先します。数値が小さいほど、優先度が高くなります。
  • プリエンプションの優先度が同じ場合は、サブ優先度を決定します。同様に、数値が小さいほど、優先度が高くなります。

5、注意が必要な事項

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


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

•リファレンス:「組み込み-STM32開発ガイド」パート2の基本-第2章サイスティックシステムタイマー(HALライブラリ)
    STM32CubeMX実用チュートリアル(3)-外部割り込み(ピットを回避するための割り込みおよびHAL_Delay関数)

おすすめ

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