Nuoeriris · 2021年01月18日

MM32F013x——TIM1硬件移相功能

相信很多做变频设计或者电机控制领域的朋友们都熟悉一项重要技术——使用单电阻电流重构技术采样相电流,实现FOC控制。那采样相电流时就涉及到低调制区域,采样时间大于PWM分段矢量作用时间,此时就需要使用移相技术,就是在中央对齐互补模式下实现非对称PWM输出。

电机控制单电阻采样机制是在一个 PWM 波形内采集两相电流 ADC 数据,但某些扇区边界条件下只能获得一路电流 ADC 数据, 需要对 PWM 波形进行变形用于构造电流采样区域。

绘图2.jpg

本文将重点介绍如何在MM32F013x上实现TIM1的硬件移相功能。

1.实现方式

目前MM32 MCU实现PWM 移相功能有多种实现方式,其中一种实现方式:设置TIM1和TIMx主从模式,开启TIMx的CCx中断,且开启对应的DMA请求通道去完成TIM1 CCRx值的改变,此外只需要在TIMX\_CCx中断服务函数中改变TIM1 对应通道的CCR值即可在软件中实现动态修改移相角度功能,同样也就实现了PWM占空比在每半个周期内交替变化。

MM32F013x系列MCU中新增 TIM1的硬件移相功能,新增了PDER(通道X输出 PWM 移相使能位) 和 CCRxFALL(通道X在 PWM 中央对齐模式向下计数时的捕获/比较值)寄存器,允许 TIM1的5 个通道在硬件上完成输出 PWM 移相操作。开启 PDER 寄存器的 PWM移相使能,根据需要移动相位,配置 CCRxFALL 以及 CCRx,即可实现 PWM 输出可编程的移相波形,可左移或是右移。

2.相关寄存器

除了之前熟悉的TIM1 PWM输出相关的寄存器外,主要还需要关注以下新增寄存器。
2.png
3.png

3.定时器1的中央对齐模式

脉冲宽度调制模式可以产生一个由 TIMx\_ARR 寄存器确定频率、由 TIMx\_CCRx 寄存器确定占空比的信号。

当 TIMx\_CR1 寄存器中的 CMS 位不为‘00’时为中央对齐模式 (所有其他的配置对 OCxREF/OCx 信号都有相同的作用)。根据不同的 CMS 位的设置,比较标志可以在计数器向上计数时被置 1、在计数器向下计数时被置 1、或在计数器向上和向下计数时被置‘1’。TIMx\_CR1寄存器中的计数方向位 (DIR) 由硬件更新,不要用软件修改它。

中央对齐模式的图例可用下图来表示:

4.png

中央对齐有3种不同模式,可以通过软件设置TIM1\_CR寄存器的CMS位来选择对应模式。3种模式中计数器的计数方式都是一样的,计数器从 0 开始计数到自动加载的值 (TIM1\_ARR - 1),产生一个计数器溢出事件,然后向下计数到 1 并且产生一个计数器下溢事件,之后再循环从 0 开始重新计数。3种模式的不同之处在于,输出比较中断标志位被设置的时刻点均不一致,根据实际需求来进行选择。

使用中央对齐模式还有以下几点需要注意:

  • 进入中央对齐模式时,使用当前的上/下计数配置;这就意味着计数器向上还是向下计数取决于 TIMx\_CR1 寄存器中 DIR 位的当前值。此外,软件不能同时修改 DIR 和 CMS位。
  • 不推荐当运行在中央对齐模式时改写计数器,因为会产生不可预知的结果。特别地:
– 如果写入计数器的值大于自动重加载的值 (TIMx\_CNT > TIMx\_ARR),则方向不会被更新
– 例如,如果计数器正在向上计数,它就会继续向上计数
– 如果将 0 或者 TIMx\_ARR 的值写入计数器,方向被更新,但不产生更新事件UEV
  • 使用中央对齐模式最保险的方法,就是在启动计数器之前产生一个软件更新 (设置 TIMx\_EGR位中的 UG 位)

4.软件实现步骤

了解完应用场景、实现原理以及涉及到的寄存器,下面介绍配置代码。

4.1 主程序初始化
extern u32 SystemCoreClock;

s32 main(void)
{
    /* TIM1 PWM GPIO AF initial */
    TIM1_GPIO_Init();

    TIM1_PWM_Init(500 - 1, SystemCoreClock / 1000000 - 1);
    DELAY_Ms(100);
    TIM1_PWM_Shift_Test() ;
}

以上为整个软件工程的入口主函数,默认主频为内部时钟HSI倍频到72M。初始化好了TIM1 前3个PWM输出通道所用引脚以及TIM1,并且开启TIM1一直输出PWM波形。

4.2 TIM1初始化
void TIM1_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_2);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA,GPIO_Pin_7) ;
}

以上代码完成了TIM1前3个PWM输出通道所用引脚的复用功能配置,对应的复用功能号需要根据芯片数据手册中的引脚功能定义表来获取到。

void TIM1_PWM_Shift_Init(u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2ENR_TIM1, ENABLE);

    TIM_DeInit(TIM1) ;
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Period = arr;
    TIM_TimeBaseStructure.TIM_Prescaler = psc;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 250 ;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);

    TIM_OCInitStructure.TIM_Pulse = 250 ;
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);

    TIM_OCInitStructure.TIM_Pulse = 250 ;
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM1, ENABLE);
    TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);

    TIM_Cmd(TIM1, ENABLE);
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

以上配置接口程序为时基相关参数,调用时候只需要根据实际应用情况传入不同的参数即可改变PWM输出的频率。

计数模式设置为中央对齐模式1,输出比较模式设置为PWM1输出模式,输出有效极性设置为高电平。当计时器值小于比较器设定值时则对应通道输出有效高电平,当计时器值大于或等于比较器设定值时则对应通道输出无效低电平。

void TIM1_PWM_Shift_Test(void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_7) ;

    TIM_SetCCR2FALL(TIM1, 200);
    TIM_SetCCR3FALL(TIM1, 300);

    TIM_PWMShiftConfig(TIM1, TIM_PDER_CCR2SHIFTEN|TIM_PDER_CCR3SHIFTEN, ENABLE);
}

TIM\_PWMShiftConfig库函数实现开启或关闭对应通道输出PWM移相功能。TIM\_SetCCRxFALL库函数实现设置对应通道在PWM中央对齐模式向下计数时的捕获/比较值。开启 PDER 寄存器的PWM移相使能后,根据需要移动相位,配置 CCRxFALL 以及 CCRX,即可实现PWM 输出可编程的移相波形,即可以左移亦或是右移。

5.测试验证

本次微课堂实验是基于eMiniboard MB-025硬件资源完成的,前述代码中,通过设置TIM1的时基为1KHz,且不开启OC1通道的移相功能,只使能OC2和OC3通道的允许输出PWM移相使能位,通过逻辑分析仪抓取TIM1 前3个PWM输出通道的波形,稳定的波形结果如下图所示:

5.png

粉红色表示通道1波形,深蓝色表示通道2波形,浅绿色表示通道3波形,黄色表示开始移相时刻点。图中看出,通道2较通道1往右移了18度的相位(最大只能移动180度,这里占用时长为500US,右移了50US为18度),通道2较通道1往左移了18度的相位(左移了50US为18度)。根据上述波形结果展示,TIM1 的硬件PWM移相功能可以配置相关寄存器的配置即可实现,操作简单。

推荐阅读
关注数
6143
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息