学习嵌入式入门(九)高级定时器及实验

一、高级定时器简介

       高级定时器的框图和通用定时器框图很类似,只是添加了其它的一些功能,如:重复计数 器、带死区控制的互补输出通道、断路输入等。这些功能在高级定时器框图的位置如下:

重复计数器

      在 F1 系列中,高级定时器 TIM1 TIM8 都有重复计数器。我们知道定时器发生上溢或者下溢时,会 直接生成更新事件。但是有重复计数器的定时器并不完全是这样的,定时器每次发生上溢或下 溢时,重复计数器的值会减一,当重复计数器的值为 0 时,再发生一次上溢或者下溢才会生成 定时器更新事件。如果我们设置重复计数器寄存器 RCR 的值为 N,那么更新事件将在定时器发 生 N+1 次上溢或下溢时发生。

输出比较

        高级定时器输出比较部分和通用定时器相比,多了带死区控制的互补输出功能。第②部分的 TIMx_CH1NTIMx_CH2N TIMx_CH3N 分别是定时器通道 1、通道 2 和通道 3 的互补输出通道,通道 4 是没有互补输出通道的DTG 是死区发生器,死区时间由 DTG[7:0]位 来配置。如果不使用互补通道和死区时间控制,那么高级定时器 TIM1 TIM8 和通用定时器 的输出比较部分使用方法基本一样,只是要注意 MOE 位得置 1 定时器才能输出。

断路功能

       断路功能也称刹车功能,一般用于电机控制的刹车。F1 系列有一个断路通道,断路源可以是刹车输入引脚(TIMx_BKIN),也可以是一个时钟失败事件。时钟失败事件由复位时钟控制器中的时钟安全系统产生。系统复位后,断路功能默认被禁止,MOE 位为低。 使能断路功能的方法:将 TIMx_BDTR 的位 BKE 1。断路输入引脚 TIMx_BKIN 的输入有效电平可通过 TIMx_BDTR 寄存器的位 BKP 设置。 使能刹车功能后:由 TIMx_BDTR MOEOSSIOSSR 位,TIMx_CR2 OISxOISxN 位,TIMx_CCER CCxECCxNE 位控制 OCx OCxN 输出状态。无论何时,OCx OCxN 输出都不能同时处在有效电平。

二、高级定时器输出指定个数 PWM 实验

  要实现定时器输出指定个数 PWM,只需要掌握下面几点内容:

1、需要把 MOE 位置 1,这样高级定时 器的通道才能输出。

2、要清楚重复计数器特性,设置重复计数器寄存器 RCR 的值为 N,那么更新事件将在定时器发生 N+1 次上溢或下溢时发生。

3、为了保证定时器输出指定个数的 PWM 后,定时器马上停止继续输出。

1、控制寄存器 1(TIMx_CR1)

2、捕获/比较模式寄存器 1/2(TIMx_CCMR1/2)

3、捕获/比较使能寄存器(TIMx_ CCER)

要让 TIM1 的 CH1 输出 PWM 波为例,该寄存器的模式设置位 OC1M[2:0]就是对应着通道 1 的模式设置,此 部分由 3 位组成,总共可以配置成 8 种模式,我们使用的是 PWM 模式,所以这 3 位必须设置为 110 或者 111,分别对应 PWM 模式 1 和 PWM 模式 2。

4、捕获/比较使能寄存器(TIMx_ CCER)

        该寄存器比较简单,要让 TIM1 的 CH1 输出 PWM 波,这里我们要使能 CC1E 位,该位是通道 1 输入/输出使能位,要想 PWM 从 IO 口输出,这个位必须设置为 1。

5、事件产生寄存器(TIMx_ EGR)

       UG 位是更新事件的控制位,作用和定时器溢出时产生的更新事件一样,区别是这里是通过软件产生的,而定时器溢出是硬件自己完成的。

6、重复计数器寄存器(TIMx_ RCR)

     重复计数器寄存器用于设置重复计数器值,因为它具有影子寄存器,所以它本身只是起缓 冲作用。

7、捕获/比较寄存器 1/2/3/4(TIMx_CCR1/2/3/4)

        在输出模式下,捕获/比较寄存器影子寄存器的值与 CNT 的值比较,根据比较结果产生相 应动作,利用这点,我们通过修改这个寄存器的值,就可以控制 PWM 的占空比了。

8、断路和死区寄存器(TIMx_ BDTR)

       高级定时器 TIM1/8 的通道用作输出时,还必须配置断路和死区寄存器(TIMx_BDTR)的位 MOE,该寄存器各位描述所示:

1、定时器输出指定个数 PWM 配置步骤

1)开启 TIMx 和通道输出的 GPIO 时钟,配置该 IO 口的复用功能输出

首先开启 TIMx 的时钟,然后配置 GPIO 为复用功能输出。

__HAL_RCC_TIM8_CLK_ENABLE(); /* 使能定时器 8 */ 
__HAL_RCC_GPIOC_CLK_ENABLE(); /* 开启 GPIOC 时钟 */ 

 2)初始化 TIMx,设置 TIMx 的 ARR 和 PSC 等参数

      使用定时器的 PWM 模式功能时,我们调用的是 HAL_TIM_PWM_Init 函数来初始化定时 器 ARR 和 PSC 等参数。

3)设置定时器为 PWM 模式,输出比较极性,比较值等参数

      在 HAL 库中,通过 HAL_TIM_PWM_ConfigChannel 函数来设置定时器为 PWM1 模式或者 PWM2 模式,根据需求设置输出比较的极性,设置比较值(控制占空比)等。

4)使能定时器更新中断,开启定时器并输出 PWM,配置定时器中断优先级

        通过__HAL_TIM_ENABLE_IT 函数使能定时器更新中断。 通过 HAL_TIM_PWM_Start 函数使能定时器并开启输出 PWM。 通过 HAL_NVIC_EnableIRQ 函数使能定时器中断。 通过 HAL_NVIC_SetPriority 函数设置中断优先级。

5)编写中断服务函数

         定时器中断服务函数为:TIMx_IRQHandler 等,当发生中断的时候,程序就会执行中断服务函数。HAL 库提供了一个定时器中断公共处理函数 HAL_TIM_IRQHandler,该函数会根据中 断类型调用相关的中断回调函数。

程序解析

atim.h

#define ATIM_TIMX_NPWM_CHY_GPIO_PORT GPIOC 
#define ATIM_TIMX_NPWM_CHY_GPIO_PIN GPIO_PIN_6 
#define ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE() do{__HAL_RCC_GPIOC_CLK_ENABLE();\ 
}while(0) /* PC 口时钟使能 */ 
#define ATIM_TIMX_NPWM TIM8 
#define ATIM_TIMX_NPWM_IRQn TIM8_UP_IRQn 
#define ATIM_TIMX_NPWM_IRQHandler TIM8_UP_IRQHandler 
#define ATIM_TIMX_NPWM_CHY TIM_CHANNEL_1 /* 通道 Y, 1<= Y <=4 */ 
#define ATIM_TIMX_NPWM_CHY_CCRX TIM8->CCR1 /* 通道 Y 的输出比较寄存器 */ 
#define ATIM_TIMX_NPWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM8_CLK_ENABLE(); \ 
}while(0) /* TIM8 时钟使能 */ 

 atim.c

void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc) 
{ 
 GPIO_InitTypeDef gpio_init_struct; 
 TIM_OC_InitTypeDef timx_oc_npwm_chy; /* 定时器输出 */ 
 ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE(); /* TIMX 通道 IO 口时钟使能 */ 
 ATIM_TIMX_NPWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */ 
 
 g_timx_npwm_chy_handle.Instance = ATIM_TIMX_NPWM; /* 定时器 x */ 
 g_timx_npwm_chy_handle.Init.Prescaler = psc; /* 定时器分频 */ 
 g_timx_npwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;/* 递增计数 */ 
 g_timx_npwm_chy_handle.Init.Period = arr; /* 自动重装载值 */ 
 g_timx_npwm_chy_handle.Init.AutoReloadPreload = 
 TIM_AUTORELOAD_PRELOAD_ENABLE; /*使能 TIMx_ARR 进行缓冲 */ 
 g_timx_npwm_chy_handle.Init.RepetitionCounter = 0; /* 重复计数器初始值 */ 
 HAL_TIM_PWM_Init(&g_timx_npwm_chy_handle); /* 初始化 PWM */ 
 
 gpio_init_struct.Pin = ATIM_TIMX_NPWM_CHY_GPIO_PIN;/* 通道 y 的 CPIO 口 */ 
 gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推完输出 */ 
 gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ 
 gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */ 
 HAL_GPIO_Init(ATIM_TIMX_NPWM_CHY_GPIO_PORT, &gpio_init_struct); 
 timx_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1; /* 模式选择 PWM 1*/ 
 timx_oc_npwm_chy.Pulse = arr / 2; /* 设置比较值,此值用来确定占空比 */ 
 timx_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */ 
 HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handle, &timx_oc_npwm_chy, 
 ATIM_TIMX_NPWM_CHY); /* 配置 TIMx 通道 y */ 
 /* 设置中断优先级,抢占优先级 1,子优先级 3 */ 
 HAL_NVIC_SetPriority(ATIM_TIMX_NPWM_IRQn, 1, 3); 
 HAL_NVIC_EnableIRQ(ATIM_TIMX_NPWM_IRQn); /* 开启 ITMx 中断 */ 
 
 __HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE);/* 允许更新中断 */ 
 HAL_TIM_PWM_Start(&g_timx_npwm_chy_handle, ATIM_TIMX_NPWM_CHY);/* 使能输出 */ 
} 

下面我们看设置 PWM 个数的函数,其定义如下:  

static uint32_t g_npwm_remain = 0; 
 
/** 
 * @brief 高级定时器 TIMX NPWM 设置 PWM 个数 
 * @param rcr: PWM 的个数, 1~2^32 次方个 
 * @retval 无 
 */ 
void atim_timx_npwm_chy_set(uint32_t npwm) 
{ 
 if (npwm == 0)return ; 
g_npwm_remain = npwm; /* 保存脉冲个数 */ 
/* 产生一次更新事件,在中断里面处理脉冲输出 */ 
 HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE); 
 __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle); /* 使能定时器 TIMX */ 
}

 下面来介绍定时器中断服务函数,其定义如下:

void ATIM_TIMX_NPWM_IRQHandler(void) 
{ 
 uint16_t npwm = 0; 
 /* 以下代码没有使用定时器 HAL 库共用处理函数来处理,而是直接通过判断中断标志位的方式 */ 
 if(__HAL_TIM_GET_FLAG(&g_timx_npwm_chy_handle, TIM_FLAG_UPDATE) != RESET) 
 { 
 if (g_npwm_remain >= 256) /* 还有大于 256 个脉冲需要发送 */ 
 { 
g_npwm_remain=g_npwm_remain - 256; 
 npwm = 256; 
 } 
 else if (g_npwm_remain % 256) /* 还有位数(不到 256)个脉冲要发送 */ 
 { 
 npwm = g_npwm_remain % 256; 
 g_npwm_remain = 0; /* 没有脉冲了 */ 
 } 
 if (npwm) /* 有脉冲要发送 */ 
 { 
 ATIM_TIMX_NPWM->RCR = npwm - 1; /* 设置 RCR 值为 npwm-1, 即 npwm 个脉冲 */ 
 HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, 
TIM_EVENTSOURCE_UPDATE); /* 产生一次更新事件,以更新 RCR 寄存器 */ 
 __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle); /* 使能定时器 TIMX */ 
 } 
 else 
 { 
/* 关闭定时器 TIMX,使用__HAL_TIM_DISABLE 需要失能通道输出,所以不用 */ 
 ATIM_TIMX_NPWM->CR1 &= ~(1 << 0); 
 } 
/* 清除定时器更新中断标志位 */ 
 __HAL_TIM_CLEAR_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE); 
 } 
}

 main.c

int main(void) 
{ 
 uint8_t key = 0; 
uint8_t t = 0; 
GPIO_InitTypeDef gpio_init_struct; 
 
 HAL_Init(); /* 初始化 HAL 库 */ 
 sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ 
 delay_init(72); /* 延时初始化 */ 
 usart_init(115200); /* 串口初始化为 115200 */ 
 led_init(); /* 初始化 LED */ 
key_init(); /* 初始化按键 */ 
 
/* 将 LED1 引脚设置为输入模式, 避免和 PC6 冲突 */ 
 gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1 引脚 */ 
 gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 设置输入状态 */ 
 gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ 
 gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM; /* 中速 */ 
 HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化 LED1 引脚 */ 
 
 atim_timx_npwm_chy_init(5000 - 1, 7200 - 1);/*10Khz 的计数频率,2hz 的 PWM 频率*/ 
/* 设置 PWM 占空比,50%,这样可以控制每一个 PWM 周期,LED1(BLUE) 有一半时间是亮的, 
一半时间是灭的,LED1 亮灭一次,表示一个 PWM 波 */ 
ATIM_TIMX_NPWM_CHY_CCRX = 2500; 
atim_timx_npwm_chy_set(5); /* 输出 5 个 PWM 波(控制 LED1)闪烁 5 次) */ 
 
 while (1) 
 { key = key_scan(0); 
 if (key == KEY0_PRES) /* KEY0 按下 */ 
 { 
 gtim_timx_npwm_chy_set(5); /* 输出 5 个 PWM 波(控制 LED1 闪烁 5 次) */ 
 } 
 t++; 
 delay_ms(10); 
 if (t > 50) /* 控制 LED1 闪烁, 提示程序运行状态 */ 
 { 
 t = 0; 
 LED0_TOGGLE(); 
 } 
 } 
} 

 三、高级定时器输出比较模式实验

      本实验我们来学习使用高级定时器输出比较模式下翻转功能,通过定时器 4 个通道分别输 出 4 个 50%占空比、不同相位的 PWM。

       输出比较模式下翻转功能作用是:当计数器的值等于捕获/比较寄存器影子寄存器的值时, OC1REF 发生翻转,进而控制通道输出(OCx)翻转。通过翻转功能实现输出 PWM 的具体原 理如下:PWM 频率由自动重载寄存器(TIMx_ARR)的值决定,在这个过程中,只要自动重载 寄存器的值不变,那么 PWM 占空比就固定为 50%。我们可以通过捕获/比较寄存器(TIMx_CCRx) 的值改变 PWM 的相位。

   

TIM1/TIM8 寄存器  

位 7(APRE)用于控制自动重载寄存 器是否具有缓冲作用。

位 4(DIR)用于配置计数器的计数方向,本实验默认置 0 即可。

位 CEN 位,用于使能计数器的工作,必须要设置该位为 1,才可以开始计数。 

捕获/比较模式寄存器 1/2(TIMx_CCMR1/2)

   TIM1/TIM8 的捕获/比较模式寄存器(TIMx_CCMR1/2),该寄存器一般有 2 个: TIMx_CCMR1 和 TIMx _CCMR2。TIMx_CCMR1 控制 CH1 和 CH2,而 TIMx_CCMR2 控制 CH3 和 CH4。

捕获/比较使能寄存器(TIMx_ CCER)  

TIM1/TIM8 的捕获/比较使能寄存器,该寄存器控制着各个输入输出通道的开关和极性。

捕获/比较寄存器 1/2/3/4(TIMx_ CCR1/2/3/4)  

TIM1/TIM8 断路和死区寄存器(TIMx_ BDTR)

定时器的 HAL 库驱动

1. HAL_TIM_OC_Init 函数

HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim); 

函数描述: 用于初始化定时器的输出比较模式。 

函数形参: 形参 1 是 TIM_HandleTypeDef 结构体类型指针变量。  

2. HAL_TIM_OC_ConfigChannel 函数

HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, 
TIM_OC_InitTypeDef *sConfig, uint32_t Channel);

函数描述: 该函数用于初始化定时器的输出比较通道。 

函数形参: 形参 1 是 TIM_HandleTypeDef 结构体类型指针变量,用于配置定时器基本参数。

形参 2  是 TIM_OC_InitTypeDef 结构体类型指针变量,用于配置定时器的输出比较参数。 

形参 3 是定时器通道,范围:TIM_CHANNEL_1 到 TIM_CHANNEL_4。  

3. HAL_TIM_OC_Start 函数

HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel); 

函数描述: 用于启动定时器的输出比较模式。

函数形参: 形参 1 是 TIM_HandleTypeDef 结构体类型指针变量。

形参 2 是定时器通道,范围:TIM_CHANNEL_1 到 TIM_CHANNEL_4。

定时器输出比较模式配置步骤

1)开启 TIMx 和通道输出的 GPIO 时钟,配置该 IO 口的复用功能输出。

2)初始化 TIMx,设置 TIMx 的 ARR 和 PSC 等参数。

3)设置定时器为输出比较模式,输出比较极性,输出比较值、翻转功能等参数。

4)开启定时器并输出 PWM

atim.h

#define ATIM_TIMX_COMP_CH1_GPIO_PORT GPIOC 
#define ATIM_TIMX_COMP_CH1_GPIO_PIN GPIO_PIN_6 
#define ATIM_TIMX_COMP_CH1_GPIO_CLK_ENABLE() 
do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC 口时钟使能 */ 
 
#define ATIM_TIMX_COMP_CH2_GPIO_PORT GPIOC 
#define ATIM_TIMX_COMP_CH2_GPIO_PIN GPIO_PIN_7 
#define ATIM_TIMX_COMP_CH2_GPIO_CLK_ENABLE() 
do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC 口时钟使能 */ 
 
#define ATIM_TIMX_COMP_CH3_GPIO_PORT GPIOC 
#define ATIM_TIMX_COMP_CH3_GPIO_PIN GPIO_PIN_8 
#define ATIM_TIMX_COMP_CH3_GPIO_CLK_ENABLE() 
do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC 口时钟使能 */ 
 
#define ATIM_TIMX_COMP_CH4_GPIO_PORT GPIOC 
#define ATIM_TIMX_COMP_CH4_GPIO_PIN GPIO_PIN_9 
#define ATIM_TIMX_COMP_CH3_GPIO_CLK_ENABLE() 
do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC 口时钟使能 */ 
 
#define ATIM_TIMX_COMP TIM8 
#define ATIM_TIMX_COMP_CH1_CCRX ATIM_TIMX_COMP->CCR1 /* 通道 1 的输出比较寄存器 */ 
#define ATIM_TIMX_COMP_CH2_CCRX ATIM_TIMX_COMP->CCR2 /* 通道 2 的输出比较寄存器 */

#define ATIM_TIMX_COMP_CH3_CCRX ATIM_TIMX_COMP->CCR3 /* 通道 3 的输出比较寄存器 */ 
#define ATIM_TIMX_COMP_CH4_CCRX ATIM_TIMX_COMP->CCR4 /* 通道 4 的输出比较寄存器 */ 
#define ATIM_TIMX_COMP_CLK_ENABLE() 
do{ __HAL_RCC_TIM8_CLK_ENABLE();}while(0) /* TIM8 时钟使能 */ 

         可以把上面的宏定义分成两部分,第一部分是定时器 1 输出通道 1~通道 4 对应的 IO 口的 宏定义。第二部分则是定时器 8 的相应宏定义。

atim.c

void atim_timx_comp_pwm_init(uint16_t arr, uint16_t psc) 
{ 
 TIM_OC_InitTypeDef timx_oc_comp_pwm = {0}; 
 
 g_timx_comp_pwm_handle.Instance = ATIM_TIMX_COMP; /* 定时器 x */ 
 g_timx_comp_pwm_handle.Init.Prescaler = psc ; /* 定时器分频 */ 
 g_timx_comp_pwm_handle.Init.CounterMode = TIM_COUNTERMODE_UP;/* 递增计数 */ 
 g_timx_comp_pwm_handle.Init.Period = arr; /* 自动重装载值 */ 
g_timx_comp_pwm_handle.Init.AutoReloadPreload = 
TIM_AUTORELOAD_PRELOAD_ENABLE; /* 使能影子寄存器 TIMx_ARR */ 
 HAL_TIM_OC_Init(&g_timx_comp_pwm_handle); /* 输出比较模式初始化 */ 
 
 timx_oc_comp_pwm.OCMode = TIM_OCMODE_TOGGLE; /* 比较输出模式翻转功能 */ 
 timx_oc_comp_pwm.Pulse = 250 - 1; /* 设置输出比较寄存器的值 */ 
 timx_oc_comp_pwm.OCPolarity = TIM_OCPOLARITY_HIGH;/* 输出比较极性为高 */ 
HAL_TIM_OC_ConfigChannel(&g_timx_comp_pwm_handle, &timx_oc_comp_pwm, 
TIM_CHANNEL_1); /* 初始化定时器的输出比较通道 1 */ 
/* CCR1 寄存器预装载使能 */ 
 __HAL_TIM_ENABLE_OCxPRELOAD(&g_timx_comp_pwm_handle, TIM_CHANNEL_1); 
 
 tim_oc_handle.Pulse = 500; 
HAL_TIM_OC_ConfigChannel(&g_timx_comp_pwm_handle, &tim_oc_handle, 
TIM_CHANNEL_2); /* 初始化定时器的输出比较通道 2 */ 
/* CCR2 寄存器预装载使能 */ 
 __HAL_TIM_ENABLE_OCxPRELOAD(&g_timx_comp_pwm_handle, TIM_CHANNEL_2); 
 
 tim_oc_handle.Pulse = 750; 
HAL_TIM_OC_ConfigChannel(&g_timx_comp_pwm_handle, &tim_oc_handle, 
TIM_CHANNEL_3); /* 初始化定时器的输出比较通道 3 */ 
/* CCR3 寄存器预装载使能 */ 
 __HAL_TIM_ENABLE_OCxPRELOAD(&g_timx_comp_pwm_handle, TIM_CHANNEL_3); 
 tim_oc_handle.Pulse = 1000; 
HAL_TIM_OC_ConfigChannel(&g_timx_comp_pwm_handle, &tim_oc_handle, 
TIM_CHANNEL_4); /* 初始化定时器的输出比较通道 4 */ 
/* CCR4 寄存器预装载使能 */ 
 __HAL_TIM_ENABLE_OCxPRELOAD(&g_timx_comp_pwm_handle, TIM_CHANNEL_4); 
 
 HAL_TIM_OC_Start(&g_timx_comp_pwm_handle, TIM_CHANNEL_1); 
 HAL_TIM_OC_Start(&g_timx_comp_pwm_handle, TIM_CHANNEL_2); 
 HAL_TIM_OC_Start(&g_timx_comp_pwm_handle, TIM_CHANNEL_3); 
 HAL_TIM_OC_Start(&g_timx_comp_pwm_handle, TIM_CHANNEL_4); 
} 
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) 
{ 
 if (htim->Instance == ATIM_TIMX_COMP) 
 { 
 GPIO_InitTypeDef gpio_init_struct; 
 
 ATIM_TIMX_COMP_CLK_ENABLE(); 
 
 ATIM_TIMX_COMP_CH1_GPIO_CLK_ENABLE(); 
 ATIM_TIMX_COMP_CH2_GPIO_CLK_ENABLE(); 
 ATIM_TIMX_COMP_CH3_GPIO_CLK_ENABLE(); 
 ATIM_TIMX_COMP_CH4_GPIO_CLK_ENABLE(); 
 
 gpio_init_struct.Pin = ATIM_TIMX_COMP_CH1_GPIO_PIN; 
 gpio_init_struct.Mode = GPIO_MODE_AF_PP; 
 gpio_init_struct.Pull = GPIO_NOPULL; 
 gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; 
 HAL_GPIO_Init(ATIM_TIMX_COMP_CH1_GPIO_PORT, &gpio_init_struct); 
 
 gpio_init_struct.Pin = ATIM_TIMX_COMP_CH2_GPIO_PIN; 
 HAL_GPIO_Init(ATIM_TIMX_COMP_CH2_GPIO_PORT, &gpio_init_struct); 
 
 gpio_init_struct.Pin = ATIM_TIMX_COMP_CH3_GPIO_PIN; 
 HAL_GPIO_Init(ATIM_TIMX_COMP_CH3_GPIO_PORT, &gpio_init_struct); 
 
 gpio_init_struct.Pin = ATIM_TIMX_COMP_CH4_GPIO_PIN; 
 HAL_GPIO_Init(ATIM_TIMX_COMP_CH4_GPIO_PORT, &gpio_init_struct); 
 } 
} 

main.c

int main(void) 
{ 
uint8_t t = 0; 
 HAL_Init(); /* 初始化 HAL 库 */ 
 sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ 
 delay_init(72); /* 延时初始化 */ 
 usart_init(115200); /* 串口初始化为 115200 */ 
led_init(); /* 初始化 LED */ 
atim_timx_comp_pwm_init(1000 - 1, 72 - 1); /* 1Mhz 的计数频率 1Khz 的周期. */ 
 ATIM_TIMX_COMP_CH1_CCRX = 250 - 1; /* 通道 1 相位 25% */ 
 ATIM_TIMX_COMP_CH2_CCRX = 500 - 1; /* 通道 2 相位 50% */ 
 ATIM_TIMX_COMP_CH3_CCRX = 750 - 1; /* 通道 3 相位 75% */ 
ATIM_TIMX_COMP_CH4_CCRX = 1000 - 1; /* 通道 4 相位 100% */
 while (1) 
 { 
 delay_ms(10); 
 t++ 
 if (t >= 20) 
 { 
 LED0_TOGGLE(); /* LED0(RED)闪烁 */ 
 t = 0; 
 } 
 } 
}

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值