[应用相关] N32使用定时器TIM1注意事项

[复制链接]
58|0
Xiashiqi 发表于 2025-11-6 09:08 | 显示全部楼层 |阅读模式
在N32G003上进行裸机驱动代码编写时,碰到一个使用TIM1输出PWM一直没有波形的问题。
本来想着以自己多年的开发经验,写个裸机的驱动不是轻而易举,没想到还是花费了点时间,这里发出来和大家分享一下。

1. N32G003定时器介绍

34766690bf5109160a.png

N32具备3个我们常用的定时器,分别是TIM1(高级定时器),TIM3(通用定时器)、TIM6(基本定时器)

实际上高级、通用、基本之间的区别就是支持的功能不同,大概关系是(高级(通用(基本))。

2. TIM1定时器介绍
2.1 主要特性
在使用TIM1之前我们需要先了解下这个高级定时器。

24080690bf4fc952ef.png

2.2 通道介绍
通道与引脚之间的关系

通过2.1 定时器的特性,我们可以看到TIM1具有5个CH。

这里的通道(CH) 实际上就是定时器用于和外部进行交互的通道。
例如当我们使用输入捕获时,选中了TIM1的通道1、2、3,那我们对应的就需要是使能相应的引脚。并将其复用为此功能。当我们要做互补输出时,也要有对应的引脚用于输出,这个我们要按照芯片的引脚定义去进行配置的。
下图是N32G003中定时器通道和GPIO引脚之间的映射关系

54438690bf4f458b61.png

通道的工作模式

定时器的每个通道都能够被配置为不同的功能,具体功能取决于我们配置的定时器工作模式。

输入捕获模式:用于捕获外部信号的变化(例如脉冲计数、频率技术)。
输出比较模式: 用于生成特定的输出脉冲。
PWM输出模式:用于控制暑促和PWM信号,常用于驱动外部设备(如蜂鸣器、马达)
互补输出模式:常用于输出互补信号的场景,如H桥驱动的点击控制,同时配合死区进行使用。
3. 使用TIM1输出PWM
3.1 定时器产生PWM的工作原理
对于PWM来说,一般有2部分比较重要,分别是频率还有占空比。

其中频率我们可以通过控制定时器的预分频值以及重装载值来进行控制。
而占空比我们则是通过配置定时器为比较模式,通过调节比较值来调节占空比。具体占空比为

占空比 = 比较值/重装载值 * 100%
例如 占空比30% =  比较值30 / 重装载值100 * 100%


那么我们产生PWM的方式也有两种

通过定时器的输出比较模式,直接在定时器回调中手动设置GPIO高或低,精度比较差,灵活性比较高
通过定时器的PWM输出模式,计时完成后定时器会自动帮把配置为PWM输出模式的引脚,进行电平的翻转产生PWM波。精度高,而且无需我们再进行编码控制。(本次主要采用这种房四海)
3.2 正确初始化GPIO(代码)
我们本次使用PA7作为PWM的输出接口,选择复用TIM1的CH2,所以在初始化引脚PA7时,我们需要将其配置为TIM1_CH2的引脚复用功能。

98238690bf4e7153f1.png

初始化PA7引脚

RCC_APB_Peripheral_Clock_Enable(RCC_APB_PERIPH_IOPA);

GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_7
GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_TIM1; // 复用定时器的PWM功能
GPIO_InitStructure.GPIO_Current = GPIO_HIGH_DREIVE;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
RCC_APB_Peripheral_Clock_Enable(RCC_APB_PERIPH_AFIO);;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


GPIO的配置中有两个点需要注意下

正确的配置gpio的mode
下图的意思是,如果我们要使用TIM1的输出比较通道,那么需要将GPIO配置为推挽复用输出模式。大家在配置引脚的工作模式时一定要参考下这部分的说明。
这里我们将GPIO的mode配置为了GPIO_MODE_AF_PP

77287690bf4dd66c18.png

正确的选择GPIO_Alternate

77052690bf4d30f21a.png

通过上图我们可以看到可以复用TIM1的AF有很多,那么我们怎么知道自己使用的引脚应该用哪项配置呢。
此时可以打开N32G003的用户手册,然后找到“引脚复用章节”

29039690bf4cb49aab.png

从上图我们了解到AF复用应该使用GPIO_AF4_TIM1
3.2 正确初始化TIM1(代码)
static void tim1_ch2_pwm_init(uint32_t period, uint32_t scale)
{
    OCInitType TIM_OCInitStructure;
    TIM_TimeBaseInitType TIM_TimeBaseStructure;

    /* TIM1 时钟使能 */
    RCC_TIM1_Clock_Config(RCC_TIM1_CLKSRC_PCLK);
    RCC_APB_Peripheral_Clock_Enable(RCC_APB_PERIPH_TIM1);
     /* Time 基础配置 */
    TIM_TimeBaseStructure.Period    = period;
    TIM_TimeBaseStructure.Prescaler = scale;
    TIM_TimeBaseStructure.ClkDiv    = 0;
    TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;
    TIM_Base_Initialize(TIM1, &TIM_TimeBaseStructure);

    //pwm通道配置
    TIM_OCInitStructure.OcMode      = TIM_OCMODE_PWM1;
    TIM_OCInitStructure.OcPolarity  = TIM_OC_POLARITY_HIGH;
    TIM_OCInitStructure.OcIdleState = TIM_OC_IDLE_STATE_RESET;
    TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
    TIM_OCInitStructure.Pulse       = 0;

    TIM_Output_Channel2_Initialize(TIM1, &TIM_OCInitStructure);
    TIM_Output_Channel2_Preload_Set(TIM1, TIM_OC_PRELOAD_ENABLE);

    TIM_Auto_Reload_Preload_Enable(TIM1);

    /* 使能TIM1 */
    TIM_On(TIM1);

    //高级定时器需要打开这个
    TIM_PWM_Output_Enable(TIM1);
}



//200Khz输出
tim1_ch2_pwm_init(240 -1, 48 - 1);


需要注意的点

TIM1要进行时钟配置
高级定时器在做PWM输出时,要使能。通用定时器就不需要,这个是很重要的。
TIM_PWM_Output_Enable(TIM1);


4. 参考资料
《MCU-MPU-SOC)_N32G003F5S7_规格书_WJ1476434.PDF》
《N32G003 系列 32-bit ARM®Cortex®-M0 微控制器 用户手册 V1.1.0.PDF》
————————————————
版权声明:本文为CSDN博主「蜘蛛-侦探」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Dr_chaser/article/details/144992618

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

本版积分规则

105

主题

310

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部