OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 585|回复: 0

《M144Z-M3最小系统板使用指南——STM32F103版》第二十二章 高级定时器输出比较模式实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-4-11 15:26:54 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-4-11 15:26 编辑

第二十二章 高级定时器输出比较模式实验

1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板

2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boar ... _mini_sysboard.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32技术交流QQ群:725095144

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章将介绍使用STM32F103的高级定时器输出多个频率、占空比相同但相位不同的PWM。通过本章的学习,读者将学习到高级定时器输出比较的匹配时输出翻转模式的使用。
本章分为如下几个小节:
22.1 硬件设计
22.2 程序设计
22.3 下载验证

22.1 硬件设计
22.1.1 例程功能
1. PC6和PC7引脚输出频率同为500Hz,但相位相差25%的PWM
2. LED0闪烁,提示程序正在运行
22.1.2 硬件资源
1. LED
       LED0 - PB5
2. TIM8
       CH1 - PC6
       CH2 - PC7

22.1.3 原理图
本章实验使用的TIM8为STM32F103的片上资源,因此没有对应的连接原理图。

22.2 程序设计
22.2.1 HAL库的TIM驱动
本章实验将使用TIM8输出四个频率、占空比相同,但相位不同的PWM,其具体步骤如下:
①:初始化定时器输出比较
②:配置定时器输出比较通道
③:开始定时器输出比较
在HAL库中对应的驱动函数如下:
①:初始化定时器输出比较
该函数用于初始化定时器输出比较,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240410142552.png
表22.2.1.1 函数HAL_TIM_OC_Init()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240410142604.png
表22.2.1.2 函数HAL_TIM_OC_Init()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     TIM_HandleTypeDef tim_handle = {0};
  5.    
  6.     /* 初始化TIM8输出比较 */
  7.     tim_handle.Instance = TIM8;
  8.     tim_handle.Init.Prescaler = 72 - 1;
  9.     tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
  10.     tim_handle.Init.Period = 1000 - 1;
  11.     tim_handle.Init.AutoReloadPreload =TIM_AUTORELOAD_PRELOAD_ENABLE;
  12.     tim_handle.Init.RepetitionCounter = 0;
  13.     HAL_TIM_OC_Init(&tim_handle);
  14. }
复制代码
②:配置定时器输出比较通道
该函数用于配置定时器的输出比较通道,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(    TIM_HandleTypeDef *htim,
  2.                                                  TIM_OC_InitTypeDef*sConfig,
  3.                                                  uint32_t Channel);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240410142616.png
表22.2.1.3 函数HAL_TIM_OC_ConfigChannel()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240410142623.png
表22.2.1.4 函数HAL_TIM_OC_ConfigChannel()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     TIM_OC_InitTypeDeftim_oc_init_struct = {0};
  5.    
  6.     /* 配置定时器通道1输出比较 */
  7.     tim_oc_init_struct.OCMode = TIM_OCMODE_TOGGLE;
  8.     tim_oc_init_struct.Pulse = 500 - 1;
  9.     tim_oc_init_struct.OCPolarity =TIM_OCPOLARITY_HIGH;
  10.     HAL_TIM_OC_ConfigChannel(&tim_handle, &tim_oc_init_struct, TIM_CHANNEL_1);
  11. }
复制代码
③:开始定时器输出比较
该函数用于开始定时器的输出比较,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240410142633.png
表22.2.1.5 函数HAL_TIM_OC_Start()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240410142644.png
表22.2.1.6 函数HAL_TIM_OC_Start()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     /* 开启定时器通道1输出比较 */
  5.     HAL_TIM_OC_Start(&tim_handle, TIM_CHANNEL_1);
  6. }
复制代码
22.2.2高级定时器驱动
本章实验的高级定时器驱动主要负责向应用层提供高级定时器的初始化函数。本章实验中,高级定时器的驱动代码包括atim.c和atim.h两个文件。
高级定时器驱动中,对TIM、GPIO的相关宏定义,如下所示:
  1. #define ATIM_TIMX_COMP TIM8
  2. #define ATIM_TIMX_COMP_CLK_ENABLE()    \
  3.     do {                                \
  4.          __HAL_RCC_TIM8_CLK_ENABLE();   \
  5.     }while (0)
  6. #define ATIM_TIMX_COMP_CH1_GPIO_PORT   GPIOC
  7. #define ATIM_TIMX_COMP_CH1_GPIO_PIN    GPIO_PIN_6
  8. #define ATIM_TIMX_COMP_CH1_GPIO_CLK_ENABLE()   \
  9.     do {                                        \
  10.          __HAL_RCC_GPIOC_CLK_ENABLE();          \
  11.     }while (0)
  12. #define ATIM_TIMX_COMP_CH2_GPIO_PORT   GPIOC
  13. #define ATIM_TIMX_COMP_CH2_GPIO_PIN    GPIO_PIN_7
  14. #define ATIM_TIMX_COMP_CH2_GPIO_CLK_ENABLE()   \
  15.     do {                                        \
  16.          __HAL_RCC_GPIOC_CLK_ENABLE();          \
  17.     }while (0)
复制代码
高级定时器驱动中TIM8的初始化函数,如下所示:
  1. /**
  2. *@brief   初始化高级定时器输出比较
  3. *@param   arr: 自动重装载值
  4. *@param   psc: 预分频系数
  5. *@retval  无
  6. */
  7. voidatim_timx_comp_init(uint16_t arr, uint16_t psc)
  8. {
  9.    GPIO_InitTypeDef gpio_init_struct;
  10.    TIM_OC_InitTypeDef timx_oc_init_struct = {0};
  11.    
  12.     /* 使能相关时钟 */
  13.    ATIM_TIMX_COMP_CH1_GPIO_CLK_ENABLE();
  14.    ATIM_TIMX_COMP_CH2_GPIO_CLK_ENABLE();
  15.    ATIM_TIMX_COMP_CLK_ENABLE();
  16.    
  17.     /* 配置输出比较通道1输出引脚 */
  18.    gpio_init_struct.Pin = ATIM_TIMX_COMP_CH1_GPIO_PIN;
  19.    gpio_init_struct.Mode = GPIO_MODE_AF_PP;
  20.    gpio_init_struct.Pull = GPIO_PULLUP;
  21.    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
  22.    HAL_GPIO_Init(ATIM_TIMX_COMP_CH1_GPIO_PORT, &gpio_init_struct);
  23.    
  24.     /* 配置输出比较通道2输出引脚 */
  25.    gpio_init_struct.Pin = ATIM_TIMX_COMP_CH2_GPIO_PIN;
  26.    gpio_init_struct.Mode = GPIO_MODE_AF_PP;
  27.    gpio_init_struct.Pull = GPIO_PULLUP;
  28.    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
  29.    HAL_GPIO_Init(ATIM_TIMX_COMP_CH2_GPIO_PORT, &gpio_init_struct);
  30.     /* 初始化定时器输出比较 */
  31.    g_timx_comp_handle.Instance = ATIM_TIMX_COMP;
  32.    g_timx_comp_handle.Init.Prescaler = psc;
  33.    g_timx_comp_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
  34.    g_timx_comp_handle.Init.Period = arr;
  35.    g_timx_comp_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  36.    g_timx_comp_handle.Init.RepetitionCounter = 0;
  37.    HAL_TIM_OC_Init(&g_timx_comp_handle);
  38.     /* 配置定时器通道1输出比较 */
  39.    timx_oc_init_struct.OCMode = TIM_OCMODE_TOGGLE;
  40.    timx_oc_init_struct.Pulse = ((arr + 1) >> 2) * 1;
  41.    timx_oc_init_struct.OCPolarity = TIM_OCPOLARITY_HIGH;
  42.    HAL_TIM_OC_ConfigChannel(   &g_timx_comp_handle,
  43.                                  &timx_oc_init_struct,
  44.                                  TIM_CHANNEL_1);
  45.     /* 配置定时器通道2输出比较 */
  46.    timx_oc_init_struct.OCMode = TIM_OCMODE_TOGGLE;
  47.    timx_oc_init_struct.Pulse = ((arr + 1) >> 2) * 2;
  48.    timx_oc_init_struct.OCPolarity = TIM_OCPOLARITY_HIGH;
  49.    HAL_TIM_OC_ConfigChannel(   &g_timx_comp_handle,
  50.                                  &timx_oc_init_struct,
  51.                                  TIM_CHANNEL_2);
  52.     /* 开始定时器输出比较 */
  53.    HAL_TIM_OC_Start(&g_timx_comp_handle, TIM_CHANNEL_1);
  54.    HAL_TIM_OC_Start(&g_timx_comp_handle, TIM_CHANNEL_2);
  55. }
复制代码
在TIM8的初始化函数中,初始化了TIM8的输出比较同时配置了TIM8的输出比较通道1和通道2,最后开始了TIM8的输出比较通道1和通道2。

22.2.3 实验应用代码
本章实验的应用代码,如下所示:
  1. int main(void)
  2. {
  3.     uint8_t t = 0;
  4.    
  5.    HAL_Init();                             /* 初始化HAL库 */
  6.    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 配置时钟,72MHz */
  7.    delay_init(72);                         /* 初始化延时 */
  8.    usart_init(115200);                     /* 初始化串口 */
  9.    led_init();                             /* 初始化LED */
  10.    atim_timx_comp_init(1000 - 1, 72 - 1); /* 初始化高级定时器输出比较 */
  11.    
  12.     while (1)
  13.     {
  14.          if (++t == 20)
  15.          {
  16.              t = 0;
  17.              LED0_TOGGLE();
  18.          }
  19.          delay_ms(10);
  20.     }
  21. }
复制代码
从上面的代码中可以看到,TIM8的自动重装载值配置为(1000-1),TIM8的预分频器数值配置为(72-1),并且TIM8的时钟频率为72MHz,因此TIM8的计数频率为1MHz,且TIM8每计数1000次溢出一次,因此溢出频率为1KHz,但TIM8的两个通道配置为了匹配时输出翻转模式,因此两个通道输出的PWM频率应为500Hz。

22.3 下载验证
在完成编译和烧录操作后,可以通过示波器观察PC6引脚和PC7引脚输出的两路PWM,可以发现这两路PWM的频率都为500Hz、占空比都为50%,但相位两两相差了25%。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 04:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表