【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里面相對比較容易掌握,還有一些高級玩法,后續章節為大家做介紹。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM