打印
[软件资料]

(分享)CW32 PWM输出功能介绍

[复制链接]
999|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
脉冲宽度调制(PWM),即“Pulse Width Modulation”的缩写,简称脉宽调制,是在数字电路中达到模拟输出效果的一种手段,常见应用电机调速,照明灯调光等。

在MCU中,主要通过定时器单元来时实现PWM输出,以CW32L083VxTx为例,LPTIM,GTIM,ATIM都可以输出PWM信号。

低功耗寄存器(LPTIM)中,LPTIM 在连续模式下可以输出 PWM 波,在单次模式下可以输出单脉冲波或单次置位波形。连续模式下输出PWM波的周期和占空比由自动重载寄存器 LPTIM_ARR 和比较寄存器 LPTIM_CMP决定。

通用定时器(GTIM)中,通过设置输出比较功能,可以产生一个由重载寄存器 GTIMx_ARR 确定频率、由比较捕获寄存器 GTIMx_CCRy 确定占空比的PWM信号。每个GTIM对应有4个GTIMx_CCRy寄存器,可输出4路PWM信号。向 GTIMx_CCMR 寄存器中的 CCyM 位写入 0xE 或 0xF,能够独立地控制每个 CHy 输出PWM信号的波形。

●设置 GTIMx_CMMR.CCyM 为 0xE,当 GTIMx_CNT >= GTIMx_CCRy 时,CHy 通道输出高电平,否则输出低电平。如果 GTIMx_CCRy 中的比较值大于重载寄存器 GTIMx_ARR 的值,则 CHy 通道输出保持为低电平;如果 GTIMx_CCRy 中的比较值为 0,则 CHy 通道输出保持为高电平。

●设置 GTIMx_CMMR.CCyM 为 0xF,当 GTIMx_CNT < GTIMx_CCRy 时,CHy 通道输出高电平,否则输出低电平。如果 GTIMx_CCRy 中的比较值大于重载寄存器 GTIMx_ARR 的值,则 CHy 通道输出保持为高电平;如果 GTIMx_CCRy 中的比较值为 0,则 CHy 通道输出保持为低电平。

下图是 GTIMx_CMMR.CCyM 为 0xE、GTIMx_ARR 为 0x08 时PWM波形实例图:
高级定时器(ATIM)中有独立PWM输出模式和互补PWM输出两种模式。

●独立PWM模式可独立输出6路PWM,PWM的周期和占空比由重载寄存器ATIM_ARR和比较捕获寄存器ATIM_CHxCCRy寄存器确定。PWM 输出模式需要设置控制寄存器 ATIM_CR、滤波寄存器 ATIM_FLTR 和死区寄存器 ATIM_DTR,如下表所示:

另外比较通道 CHx 的 A 路可通过控制寄存器 ATIM_CR 的 PWM2S 位域配置为单点比较或双点比较 工作方式。在单点比较方式下,使用比较捕获寄存器 ATIM_CHxCCRA 控制比较输出;在双点比较方式下,使用 比较捕获寄存器 ATIM_CHxCCRA 和 ATIM_CHxCCRB 控制比较输出。比较通道的 B 路只能使用单点比较,由比较 捕获寄存器 ATIM_CHxCCRB 控制比较输出。

●互补PWM模式可输出3对互补输出的PWM波形,通常用于电机控制。设置控制寄存器 ATIM_CR 的 COMP 位域为 1 选择互补 PWM 输出模式,比较输出通道 CHxA 与通道 CHxB 产生一 对互补 PWM。在互补 PWM 输出模式下,通道 CHx 的 A 路控制输出信号, B 路比较捕获寄存器 CHxCCRB 不再控制 CHxB 输出,但仍可用作内部控制,比如触发 ADC 或 DMA。

另外互补 PWM 输出模式,也可通过控制寄存器 ATIM_CR 的 PWM2S 位域选择单点比较或双点比较工作方式:单点比 较时使用比较捕获寄存器 ATIM_CHxCCRA 控制比较输出;双点比较时使用比较捕获寄存器 ATIM_CHxCCRA 和 ATIM_CHxCCRB 控制比较输出。


使用特权

评论回复
沙发
豌豆爹|  楼主 | 2023-3-13 10:49 | 只看该作者

实例演示


以CW32L083VxTx的通用定时器GTIM1为例,实现PWM输出例程:GTIM1的CH3通道(PB08)输出周期为500uS,占空比递增递减循环改变的PWM信号。

1.配置不同的系统时钟。
void RCC_Configuration(void)
{
/* 0. HSI使能并校准 */
RCC_HSI_Enable(RCC_HSIOSC_DIV6);
/* 1. 设置HCLK和PCLK的分频系数 */
RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
/* 2. 使能PLL,通过HSI倍频到48MHz */
RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 6);     
// PLL输出频率48MHz
RCC_PLL_OUT();
///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle
///< 当使用的时钟源HCLK大于48M,小于等于72MHz:设置FLASH 读等待周期为3 cycle   
__RCC_FLASH_CLK_ENABLE();
FLASH_SetLatency(FLASH_Latency_2);
/* 3. 时钟切换到PLL */
RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);
RCC_SystemCoreClockUpdate(48000000);
}
2.配置GPIO口
void GPIO_Configuration(void)                                                
{
/* PB08作为GTIM1的CH3 PWM 输出 */                                                                 
    __RCC_GPIOB_CLK_ENABLE();
    PB08_AFx_GTIM1CH3();
    PB08_DIGTAL_ENABLE();
    PB08_DIR_OUTPUT();
    PB08_PUSHPULL_ENABLE();
}

3.配置中断使能
void NVIC_Configuration(void)
{
__disable_irq();
    NVIC_EnableIRQ(GTIM1_IRQn);
__enable_irq();
}

4.配置GTIM为PWM输出功能
void PWM_OutputConfig(void)
{
    GTIM_InitTypeDef GTIM_InitStruct = {0};
    __RCC_GTIM1_CLK_ENABLE();
    GTIM_InitStruct.Mode = GTIM_MODE_TIME; /*!< GTIM的模式选择。*/
    GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE;
/*!< GTIM的单次/连续计数模式选择。*/
    GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV16;
/*!< GTIM的预分频系数。*/  
// DCLK = PCLK / 16 = 48MHz/16 = 3MHz
    GTIM_InitStruct.ReloadValue = Period * 3 - 1; /*!< GTIM的重载值。*/
//ARR设置为1499
    GTIM_InitStruct.ToggleOutState = DISABLE;
    GTIM_TimeBaseInit(CW_GTIM1, &GTIM_InitStruct);
//GTIM的基础参数初始化
GTIM_OCInit(CW_GTIM1, GTIM_CHANNEL3, GTIM_OC_OUTPUT_PWM_HIGH);
       //比较输出功能初始化
    GTIM_SetCompare3(CW_GTIM1, PosWidth);
    GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE);
    GTIM_Cmd(CW_GTIM1, ENABLE);// GTIM使能
}
5.GTIM标志清零函数
void GTIM_ClearITPendingBit(GTIM_TypeDef *GTIMx, uint32_t GTIM_IT)
{
    GTIMx->ICR = ~GTIM_IT;
}

6.GTIM 比较值设置函数
void GTIM_SetCompare3(GTIM_TypeDef *GTIMx, uint32_t Value)
{
    GTIMx->CCR3 = 0x0000FFFF & Value;
}
7.GTIM中断处理函数
void GTIM1_IRQHandler(void)
{
/* USER CODE BEGIN */
// 中断每500us进入一次,每50ms改变一次PosWidth
    static uint16_t TimeCnt = 0;
    GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
    if (TimeCnt++ >= 100)    // 50ms
    {
        TimeCnt = 0;
        if (Dir)
        {
            PosWidth += 15;    // 5us
        }
        else
        {
            PosWidth -= 15;
        }
        if (PosWidth >= Period * 3)
        {
            Dir = 0;
        }
        if (0 == PosWidth)
        {
            Dir = 1;
        }
        GTIM_SetCompare3(CW_GTIM1, PosWidth);
    }
    /* USER CODE END */
}
8.主函数
uint32_t Period = 500;    // 周期,单位us
uint32_t PosWidth = 0;    // 正脉宽,单位us
uint8_t Dir = 1;    // 计数方向 1增加,0 减少

int32_t main(void)
{
    /*系统时钟配置 */
    RCC_Configuration();
    /* GPIO配置*/
    GPIO_Configuration();
    PWM_OutputConfig();
    /* NVIC配置*/
    NVIC_Configuration();
    while(1)
    {
        /* 中断服务程序见GTIM1_IRQHandler() */
    }

9.实验演示
系统时钟由HSI提供,通过PLL倍频到48MHz。GTIM1经16分频后,以3MHz的频率计数,ARR设置为1499,GTIM1的溢出周期为500us。GTIM1每500us进入一次中断,每50ms改变一次CH3的CCR寄存器的值,即改变PWM的正脉宽,步长为5us,先递增到ARR,然后递减到0,如此反复。通过示波器图像显示,PB08处的信号波的占空比随时间进行周期性变化。截取2个波形如下:


使用特权

评论回复
板凳
tpgf| | 2023-4-11 12:16 | 只看该作者
都可以实现哪些PWM输出模式呢

使用特权

评论回复
地板
aoyi| | 2023-4-11 13:25 | 只看该作者
tpgf 发表于 2023-4-11 12:16
都可以实现哪些PWM输出模式呢

有些芯片有两种pwm输出模式  有些芯片有三种输出模式

使用特权

评论回复
5
qcliu| | 2023-4-11 13:53 | 只看该作者
aoyi 发表于 2023-4-11 13:25
有些芯片有两种pwm输出模式  有些芯片有三种输出模式

感觉三种模式的比较少 大部分就是pwm1和pwm2这两种模式了

使用特权

评论回复
6
磨砂| | 2023-4-11 14:33 | 只看该作者
TIM_OCMode_PWM1  
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。

当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。


TIM_OCMode_PWM2

当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。

当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位

使用特权

评论回复
7
晓伍| | 2023-4-11 14:51 | 只看该作者
另外如果功能全的话 应该还得有一些输出比较模式的吧

使用特权

评论回复
8
八层楼| | 2023-4-11 15:40 | 只看该作者
晓伍 发表于 2023-4-11 14:51
另外如果功能全的话 应该还得有一些输出比较模式的吧

这个就得看数据手册了  有些型号的模式没有那么多的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

513

主题

1960

帖子

5

粉丝