【STM32H7教程】第64章 STM32H7的高分辨率定時器HRTIM應用之PWM實現

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第64章       STM32H7的高分辨率定時器HRTIM應用之PWM實現

本章教程為大家講解高分辨率定時器HRTIM的PWM實現。

64.1 初學者重要提示

64.2 HRTIM的PWM驅動設計

64.3 HRTIM板級支持包(bsp_tim_pwm.c)

64.4 HRTIM驅動移植和使用

64.5 實驗例程設計框架

64.6 實驗例程說明(MDK)

64.7 實驗例程說明(IAR)

64.8 總結

64.1 初學者重要提示

  1.   學習本章節前,務必優先學習第63章,HAL庫的幾個常用API均作了講解和舉例。
  2.   設置PWM周期時,注意結構體HRTIM_TimeBaseCfgTypeDef中的Period周期參數範圍,至少3個HRTIM時鐘周期,最大值0xFFDF。
  3.   HRTIM的輸出極性可以設置激活狀態Active和非激活狀態Inactive,這裡要注意一點,激活狀態既可以設置為高電平輸出,也可以設置為低電平輸出。
  4.   HRTIM其它幾個例子執行效果展示,方便大家有個感性認識:

64.2 HRTIM的PWM驅動設計

HRTIM的PWM實現相對比較簡單,只是涉及到的API比較多。

64.2.1 HRTIM時鐘設置

HRTIM支持兩種時鐘源,一個是來自CPU主頻時鐘,另一個是來自通用定時器。大家可以通過函數HAL_RCCEx_PeriphCLKConfig來設置使用那個時鐘。具體實現代碼如下:

1.    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};  2.  3.    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_HRTIM1;  4.    PeriphClkInitStruct.Hrtim1ClockSelection = RCC_HRTIM1CLK_CPUCLK;  5.    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)  6.    {  7.         Error_Handler(__FILE__, __LINE__);  8.    }

這裡把幾個關鍵的地方再闡釋下:

  • 第1行,這個變量務必要做0初始化,防止不必要的麻煩。
  • 第4行,用於配置HRTIM使用的時鐘源,這裡有兩種選擇:
    • 使用CPU主頻時鐘,對應參數RCC_HRTIM1CLK_CPUCLK。
    • 使用通用定時器時鐘,對應參數RCC_HRTIM1CLK_TIMCLK。如果CPU主頻時鐘是400MHz的話,通用定時器時鐘就是200MHz。

64.2.2 HRTIM的PWM輸出引腳

HRTIM的涉及到的輸入輸出引腳如下:

FTL = FAULT INPUT Lines  PA15       HRTIM_FLT1  PC11       HRTIM_FLT2  PD4        HRTIM_FLT3  PB3        HRTIM_FLT4  PG10       HRTIM_FLT5    EEV = EXTERN EVENT Lines  PG13       HRTIM_EEV10  PB7        HRTIM_EEV9  PB6        HRTIM_EEV8  PB5        HRTIM_EEV7  PB4        HRTIM_EEV6  PG12       HRTIM_EEV5  PG11       HRTIM_EEV4  PD5        HRTIM_EEV3  PC12       HRTIM_EEV2  PC10       HRTIM_EEV1    PC6        HRTIM_CHA1  PC7        HRTIM_CHA2  PC8        HRTIM_CHB1  PA8        HRTIM_CHB2  PA9        HRTIM_CHC1  PA10       HRTIM_CHC2  PA11       HRTIM_CHD1  PA12       HRTIM_CHD2  PG6        HRTIM_CHE1  PG7        HRTIM_CHE2    PE0        HRTIM_SCIN  PE1        HRTIM_SCOUT  PB10       HRTIM_SCOUT  PB11       HRTIM_SCIN

當前程序裏面使用的Timer D的HRTIM_CHD1和HRTIM_CHD2,即PA11和PA12引腳輸出PWM。程序配置如下:

GPIO_InitTypeDef   GPIO_InitStruct;    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  GPIO_InitStruct.Pull = GPIO_PULLUP;  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;    GPIO_InitStruct.Alternate = GPIO_AF2_HRTIM1;  GPIO_InitStruct.Pin = GPIO_PIN_11;  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    GPIO_InitStruct.Alternate = GPIO_AF2_HRTIM1;  GPIO_InitStruct.Pin = GPIO_PIN_12;  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

64.2.3 HRTIM初始化和時基配置

HRTIM的初始化和時基配置如下:

1.    /*##- 初始化HRTIM ###################################################*/  2.    HrtimHandle.Instance = HRTIM1;  /* 例化,使用的HRTIM1 */  3.    HrtimHandle.Init.HRTIMInterruptResquests = HRTIM_IT_NONE;/* 用於配置支持的中斷請求,當前配置無中斷 */  4.    HrtimHandle.Init.SyncOptions = HRTIM_SYNCOPTION_NONE;    /* 配置HRTIM作為Master,發送同步信號,或者作  5.                                                          為Slave,接收同步信號,當前配置沒有做同步功能 */  6.  7.    HAL_HRTIM_Init(&HrtimHandle);  8.  9.    /*##- 配置HRTIM的TIMER D 時基 #########################################*/  10.    sConfig_time_base.Mode = HRTIM_MODE_CONTINUOUS; /* 連續工作模式 */  11.    sConfig_time_base.Period = HRTIM_TIMD_PERIOD;   /* 設置周期 */  12.    sConfig_time_base.PrescalerRatio = HRTIM_PRESCALERRATIO_DIV1; /* 設置HRTIM分頻,當前設置的1分頻,也就  13.                                                                    是不分頻 */  14.    sConfig_time_base.RepetitionCounter = 0;                     /* 設置重複計數器為0,即不做重複計數 */  15.  16.    HAL_HRTIM_TimeBaseConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, &sConfig_time_base);

這裡把幾個關鍵的地方再闡釋下:

  •   第2-4行,初始化HRTIM。
  •   第10-16行,配置HRTIM的Timer D時基。
    •   第11行,設置Timer D的周期。

比如HRTIM主頻是400MHz,HRTIM_TIMD_PERIOD = 4000,那麼Timer D的輸出頻率如下:

PWM的頻率 = 400MHz / HRTIM_TIMD_PERIOD

                = 400000000 / 4000

                = 100KHz

  •   第12行,對於STM32H7系列,僅支持下面選項中最後三個參數,也就是1分頻,2分頻和4分頻。
#define HRTIM_PRESCALERRATIO_MUL32    (0x00000000U)  #define HRTIM_PRESCALERRATIO_MUL16    (0x00000001U)  #define HRTIM_PRESCALERRATIO_MUL8     (0x00000002U)  #define HRTIM_PRESCALERRATIO_MUL4     (0x00000003U)  #define HRTIM_PRESCALERRATIO_MUL2     (0x00000004U)  #define HRTIM_PRESCALERRATIO_DIV1     (0x00000005U)  #define HRTIM_PRESCALERRATIO_DIV2     (0x00000006U)  #define HRTIM_PRESCALERRATIO_DIV4     (0x00000007U)

64.2.4 HRTIM的Timer D配置

Timer D的配置成員非常多,對於PWM輸出功能來說,這些成員的功能有個了解即可:

HRTIM_TimerCfgTypeDef        sConfig_timerD;  sConfig_timerD.DMARequests = HRTIM_TIM_DMA_NONE;        /* 不使用DMA */  sConfig_timerD.HalfModeEnable = HRTIM_HALFMODE_DISABLED;/* 關閉HALF模式 */  sConfig_timerD.StartOnSync = HRTIM_SYNCSTART_DISABLED;   /* 設置同步輸入端接收到上升沿信號後,不啟動定時器 */  sConfig_timerD.ResetOnSync = HRTIM_SYNCRESET_DISABLED;   /* 設置同步輸入端接收到上升沿信號後,不複位定時器 */  sConfig_timerD.DACSynchro = HRTIM_DACSYNC_NONE;        /* 不使用DAC同步事件 */  sConfig_timerD.PreloadEnable = HRTIM_PRELOAD_ENABLED;     /* 使能寄存器預加載 */  sConfig_timerD.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;      /* 獨立更新,與DMA突發傳輸完成無關 */  sConfig_timerD.BurstMode = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;     /* 在突發模式下,定時器正常運行 */  sConfig_timerD.RepetitionUpdate = HRTIM_UPDATEONREPETITION_ENABLED;/* 設置重計數器事件可以觸發寄存器更新 */  /* 當HRTIM TIMER的計數器複位時或者計數回滾到0時,不觸發寄存器更新 */  sConfig_timerD.ResetUpdate = HRTIM_TIMUPDATEONRESET_DISABLED;  sConfig_timerD.InterruptRequests = HRTIM_TIM_IT_NONE;           /* 不使用中斷 */  sConfig_timerD.PushPull = HRTIM_TIMPUSHPULLMODE_DISABLED;       /* 不開啟推挽模式 */  sConfig_timerD.FaultEnable = HRTIM_TIMFAULTENABLE_NONE;         /* 不使用HRTIM TIMER的Fault通道 */  sConfig_timerD.FaultLock = HRTIM_TIMFAULTLOCK_READWRITE;         /* 不開啟HRTIM TIMER的異常使能狀態寫保護 */  sConfig_timerD.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_DISABLED;/* 不開啟死區時間插入 */  /* 不開啟HRTIM TIMER的延遲保護模式 */  sConfig_timerD.DelayedProtectionMode = HRTIM_TIMER_D_E_DELAYEDPROTECTION_DISABLED;  /* Master或TIMER(A到E)更新時,不同步更新寄存器 */  sConfig_timerD.UpdateTrigger= HRTIM_TIMUPDATETRIGGER_NONE;  sConfig_timerD.ResetTrigger = HRTIM_TIMRESETTRIGGER_NONE; /* 無複位觸發 */  HAL_HRTIM_WaveformTimerConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, &sConfig_timerD);

注意,如果HRTIM_TimerCfgTypeDef  sConfig_timerD做局部變量,務必記得清零。

64.2.5 Timer D的輸出比較配置

HRTIM用於PWM功能時,比較輸出用於設置PWM占空比:

HRTIM_CompareCfgTypeDef      sConfig_compare;    sConfig_compare.AutoDelayedMode = HRTIM_AUTODELAYEDMODE_REGULAR; /* 這裡使用標準模式,即未使用自動延遲 */  sConfig_compare.AutoDelayedTimeout = 0;              /* 由於前面的參數未使用自動延遲模式,此參數無作用 */  /*      設置定時器比較單元的比較值:      最小值要大於等於3個HRTIM時鐘周期。      最大值要小於等於0xFFFF – 1  */  sConfig_compare.CompareValue = HRTIM_TIMD_PERIOD / 2;  /* 占空比50% */  HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, HRTIM_COMPAREUNIT_1,   &sConfig_compare);  sConfig_compare.CompareValue = HRTIM_TIMD_PERIOD / 4;  /* 占空比25% */  HAL_HRTIM_WaveformCompareConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, HRTIM_COMPAREUNIT_2,   &sConfig_compare);

注意事項:

  •   如果HRTIM_CompareCfgTypeDef sConfig_compare做局部變量,務必記得清零。
  •   配置占空比就是配置成員CompareValue,範圍是0到HRTIM_TIMD_PERIOD(這個參數就是前面配置的PWM周期)。比如配置為HRTIM_TIMD_PERIOD/2就表示占空比50%,配置為HRTIM_TIMD_PERIOD/4就表示占空比25%。

64.2.6 啟動PWM輸出和Timer D的計數

這部分的實現代碼如下:

1.    HRTIM_OutputCfgTypeDef       sConfig_output_config;  2.  3.    sConfig_output_config.Polarity = HRTIM_OUTPUTPOLARITY_LOW;    /* 設置定時器輸出極性 */  4.    sConfig_output_config.SetSource = HRTIM_OUTPUTRESET_TIMCMP1;  /* 定時器比較事件1可以將輸出置位 */  5.    sConfig_output_config.ResetSource = HRTIM_OUTPUTSET_TIMPER;   /* 定時器周期性更新事件可以將輸出清零 */  6.    sConfig_output_config.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;   /* 輸出不受突發模式影響 */  7.    sConfig_output_config.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE; /* 設置空閑狀態輸出低電平 */  8.    sConfig_output_config.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;   /* 輸出不受異常輸入影響 */  9.    sConfig_output_config.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED; /* 關閉Chopper模式 */  10.    sConfig_output_config.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR; /* 設置從突發模式切換  11.                                                                             到空閑模式,不插入死區時間 */  12.  13.    HAL_HRTIM_WaveformOutputConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, HRTIM_OUTPUT_TD1,  14.                                                                    &sConfig_output_config);  15.  16.    sConfig_output_config.SetSource = HRTIM_OUTPUTRESET_TIMCMP2;  /* 定時器比較事件2可以將輸出置位 */  17.    HAL_HRTIM_WaveformOutputConfig(&HrtimHandle, HRTIM_TIMERINDEX_TIMER_D, HRTIM_OUTPUT_TD2,  18.                                                                     &sConfig_output_config);  19.  20.    /*##-9- 啟動PWM輸出 #############################################*/  21.    if (HAL_HRTIM_WaveformOutputStart(&HrtimHandle,  HRTIM_OUTPUT_TD1 + HRTIM_OUTPUT_TD2) != HAL_OK)  22.    {  23.        Error_Handler(__FILE__, __LINE__);  24.    }  25.  26.    /*##-10- 啟動計數器 #############################################*/  27.    if (HAL_HRTIM_WaveformCounterStart(&HrtimHandle, HRTIM_TIMERID_TIMER_D) != HAL_OK)  28.    {  29.        Error_Handler(__FILE__, __LINE__);  30.    }

這裡把幾個關鍵的地方再闡釋下:

  •   第1行,如果HRTIM_OutputCfgTypeDef sConfig_output_config做局部變量,務必記得清零。
  •   第3行,輸出極性是用來設置激活狀態Active對應的高電平還是低電平。
  •   第4行,用來實現置位源(SetSource)設置,這裡是設置滿足比較事件1時,輸出置位。
  •   第5行,用來實現複位源(ResetSource)設置,這裡是設置產生周期性更新事件時,輸出清零。

        通過第4行和第5行,就實現了Timer D中通道1的高低電平輸出方式,

  •   第16行,設置Timer D中通道2的置位源,即通道2的高低電平輸出方式。

64.3 HRTIM板級支持包(bsp_hrtim_pwm.c)

定時器驅動文件bsp_hrtim_pwm.c主要實現了如下一個API供用戶調用:

  •   bsp_SetHRTIMOutPWM

64.3.1 函數bsp_SetHRTIMforInt

函數原型:

void bsp_SetHRTIMOutPWM(void)

函數描述:

這個函數的源碼實現在本章64.2小節裏面已經進行了詳細說明。

當前這個函數通過配置HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%。

64.4 HRTIM驅動移植和使用

定時器的移植比較簡單:

  •   第1步:複製bsp_hrtim_pwm.c和bsp_hrtim_pwm.h到自己的工程目錄,並添加到工程裏面。
  •   第2步:這幾個驅動文件主要用到HAL庫的GPIO和HRTIM驅動文件,簡單省事些可以添加所有HAL庫.C源文件進來。
  •   第3步,應用方法看本章節配套例子即可。

64.5 實驗例程設計框架

通過程序設計框架,讓大家先對配套例程有一個全面的認識,然後再理解細節,本次實驗例程的設計框架如下:

  第1階段,上電啟動階段:

  • 這部分在第14章進行了詳細說明。

  第2階段,進入main函數:

  •   第1步,硬件初始化,主要是MPU,Cache,HAL庫,系統時鐘,滴答定時器,LED和串口。同時HRTIM也做了配置,將 HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%。
  •   第2步,按鍵應用程序設計部分。

64.6 實驗例程說明(MDK)

配套例子:

V7-045_高分辨率定時器HRTIM實現PWM輸出

實驗目的:

  1. 學習高分辨率定時器HRTIM的PWM實現。

實驗內容:

  1. 上電啟動了一個軟件定時器,每100ms翻轉一次LED2。
  2. 配置HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%。

PWM輸出引腳PA11和PA12位置:

上電後串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1

程序設計:

系統棧大小分配:

RAM空間用的DTCM:

硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*  *********************************************************************************************************  *    函 數 名: bsp_Init  *    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次  *    形    參:無  *    返 回 值: 無  *********************************************************************************************************  */  void bsp_Init(void)  {      /* 配置MPU */      MPU_Config();        /* 使能L1 Cache */      CPU_CACHE_Enable();        /*         STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:         - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。         - 設置NVIV優先級分組為4。       */      HAL_Init();        /*         配置系統時鐘到400MHz         - 切換使用HSE。         - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。      */      SystemClock_Config();        /*         Event Recorder:         - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。         - 默認不開啟,如果要使能此選項,務必看V7開發板用戶手冊第xx章      */  #if Enable_EventRecorder == 1      /* 初始化EventRecorder並開啟 */      EventRecorderInitialize(EventRecordAll, 1U);      EventRecorderStart();  #endif        bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */      bsp_InitTimer();      /* 初始化滴答定時器 */      bsp_InitUart();    /* 初始化串口 */      bsp_InitExtIO();    /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */      bsp_InitLed();        /* 初始化LED */  }

MPU配置和Cache配置:

數據Cache和指令Cache都開啟。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/*  *********************************************************************************************************  *    函 數 名: MPU_Config  *    功能說明: 配置MPU  *    形    參: 無  *    返 回 值: 無  *********************************************************************************************************  */  static void MPU_Config( void )  {      MPU_Region_InitTypeDef MPU_InitStruct;        /* 禁止 MPU */      HAL_MPU_Disable();        /* 配置AXI SRAM的MPU屬性為Write back, Read allocate,Write allocate */      MPU_InitStruct.Enable           = MPU_REGION_ENABLE;      MPU_InitStruct.BaseAddress      = 0x24000000;      MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;      MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;      MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;      MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;      MPU_InitStruct.Number           = MPU_REGION_NUMBER0;      MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;      MPU_InitStruct.SubRegionDisable = 0x00;      MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;        HAL_MPU_ConfigRegion(&MPU_InitStruct);          /* 配置FMC擴展IO的MPU屬性為Device或者Strongly Ordered */      MPU_InitStruct.Enable           = MPU_REGION_ENABLE;      MPU_InitStruct.BaseAddress      = 0x60000000;      MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;      MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;      MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;      MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;      MPU_InitStruct.Number           = MPU_REGION_NUMBER1;      MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;      MPU_InitStruct.SubRegionDisable = 0x00;      MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;        HAL_MPU_ConfigRegion(&MPU_InitStruct);        /*使能 MPU */      HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);  }    /*  *********************************************************************************************************  *    函 數 名: CPU_CACHE_Enable  *    功能說明: 使能L1 Cache  *    形    參: 無  *    返 回 值: 無  *********************************************************************************************************  */  static void CPU_CACHE_Enable(void)  {      /* 使能 I-Cache */      SCB_EnableICache();        /* 使能 D-Cache */      SCB_EnableDCache();  }

主功能:

主程序實現如下操作:

  •  上電啟動了一個軟件定時器,每100ms翻轉一次LED2。
  •  配置HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%
/*  *********************************************************************************************************  *    函 數 名: main  *    功能說明: c程序入口  *    形    參: 無  *    返 回 值: 錯誤代碼(無需處理)  *********************************************************************************************************  */  int main(void)  {      uint8_t ucKeyCode;    /* 按鍵代碼 */        bsp_Init();        /* 硬件初始化 */      PrintfLogo();    /* 打印例程名稱和版本等信息 */      PrintfHelp();    /* 打印操作提示 */          bsp_SetHRTIMOutPWM();        bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */        while (1)      {          bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和喂狗 */            /* 判斷定時器超時時間 */          if (bsp_CheckTimer(0))          {              /* 每隔100ms 進來一次 */              bsp_LedToggle(2);          }            /* 按鍵濾波和檢測由後台systick中斷服務程序實現,我們只需要調用bsp_GetKey讀取鍵值即可。 */          ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */          if (ucKeyCode != KEY_NONE)          {              switch (ucKeyCode)              {                  case KEY_DOWN_K1:            /* K1鍵按下 */                      break;                    default:                      /* 其它的鍵值不處理 */                      break;              }          }      }  }

64.7 實驗例程說明(IAR)

配套例子:

V7-045_高分辨率定時器HRTIM實現PWM輸出

實驗目的:

  1. 學習高分辨率定時器HRTIM的PWM實現。

實驗內容:

  1. 上電啟動了一個軟件定時器,每100ms翻轉一次LED2。
  2. 配置HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%。

PWM輸出引腳PA11和PA12位置:

上電後串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1

程序設計:

系統棧大小分配:

RAM空間用的DTCM:

硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*  *********************************************************************************************************  *    函 數 名: bsp_Init  *    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次  *    形    參:無  *    返 回 值: 無  *********************************************************************************************************  */  void bsp_Init(void)  {      /* 配置MPU */      MPU_Config();        /* 使能L1 Cache */      CPU_CACHE_Enable();        /*         STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:         - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。         - 設置NVIV優先級分組為4。       */      HAL_Init();        /*         配置系統時鐘到400MHz         - 切換使用HSE。         - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。      */      SystemClock_Config();        /*         Event Recorder:         - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。         - 默認不開啟,如果要使能此選項,務必看V7開發板用戶手冊第xx章      */  #if Enable_EventRecorder == 1      /* 初始化EventRecorder並開啟 */      EventRecorderInitialize(EventRecordAll, 1U);      EventRecorderStart();  #endif        bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */      bsp_InitTimer();      /* 初始化滴答定時器 */      bsp_InitUart();    /* 初始化串口 */      bsp_InitExtIO();    /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */      bsp_InitLed();        /* 初始化LED */  }

MPU配置和Cache配置:

數據Cache和指令Cache都開啟。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/*  *********************************************************************************************************  *    函 數 名: MPU_Config  *    功能說明: 配置MPU  *    形    參: 無  *    返 回 值: 無  *********************************************************************************************************  */  static void MPU_Config( void )  {      MPU_Region_InitTypeDef MPU_InitStruct;        /* 禁止 MPU */      HAL_MPU_Disable();        /* 配置AXI SRAM的MPU屬性為Write back, Read allocate,Write allocate */      MPU_InitStruct.Enable           = MPU_REGION_ENABLE;      MPU_InitStruct.BaseAddress      = 0x24000000;      MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;      MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;      MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;      MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;      MPU_InitStruct.Number           = MPU_REGION_NUMBER0;      MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;      MPU_InitStruct.SubRegionDisable = 0x00;      MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;        HAL_MPU_ConfigRegion(&MPU_InitStruct);          /* 配置FMC擴展IO的MPU屬性為Device或者Strongly Ordered */      MPU_InitStruct.Enable           = MPU_REGION_ENABLE;      MPU_InitStruct.BaseAddress      = 0x60000000;      MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;      MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;      MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;      MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;      MPU_InitStruct.Number           = MPU_REGION_NUMBER1;      MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;      MPU_InitStruct.SubRegionDisable = 0x00;      MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;        HAL_MPU_ConfigRegion(&MPU_InitStruct);        /*使能 MPU */      HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);  }    /*  *********************************************************************************************************  *    函 數 名: CPU_CACHE_Enable  *    功能說明: 使能L1 Cache  *    形    參: 無  *    返 回 值: 無  *********************************************************************************************************  */  static void CPU_CACHE_Enable(void)  {      /* 使能 I-Cache */      SCB_EnableICache();        /* 使能 D-Cache */      SCB_EnableDCache();  }

主功能:

主程序實現如下操作:

  •  上電啟動了一個軟件定時器,每100ms翻轉一次LED2。
  •  配置HRTIM的TIMER D輸出兩路PWM,周期都是100KHz,PA11引腳輸出占空比50%,PA12引腳輸出的占空比25%
/*  *********************************************************************************************************  *    函 數 名: main  *    功能說明: c程序入口  *    形    參: 無  *    返 回 值: 錯誤代碼(無需處理)  *********************************************************************************************************  */  int main(void)  {      uint8_t ucKeyCode;    /* 按鍵代碼 */        bsp_Init();        /* 硬件初始化 */      PrintfLogo();    /* 打印例程名稱和版本等信息 */      PrintfHelp();    /* 打印操作提示 */          bsp_SetHRTIMOutPWM();        bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */        while (1)      {          bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和喂狗 */            /* 判斷定時器超時時間 */          if (bsp_CheckTimer(0))          {              /* 每隔100ms 進來一次 */              bsp_LedToggle(2);          }            /* 按鍵濾波和檢測由後台systick中斷服務程序實現,我們只需要調用bsp_GetKey讀取鍵值即可。 */          ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */          if (ucKeyCode != KEY_NONE)          {              switch (ucKeyCode)              {                  case KEY_DOWN_K1:            /* K1鍵按下 */                      break;                    default:                      /* 其它的鍵值不處理 */                      break;              }          }      }  }

64.8 總結

本章節就為大家講解這麼多,PWM是HRTIM裏面相對比較容易掌握,還有一些高級玩法,後續章節為大家做介紹。