【CH559L单片机】PWM功能和示例介绍

【CH559L单片机】PWM功能和示例介绍


  • ✨在官方CH559单片机手册中,在定时器(Timer)这一章节介绍PWM。

在这里插入图片描述

⛳PWM 功能

📝CH559 的 Timer3 具有 16 位 PWM 功能,除此之外还有另外 2 路 8 位 PWM,PWM 可以选择默认的输出极性为低电平或者高电平,可以动态修改 PWM 的输出占空比,通过简单 RC 电阻电容进行积分低通滤波后,即可获得各种输出电压,相当于低速数模转换器 DAC。
  • 🌿PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END
    则按 100%处理。
  • 🌿PWM1 输出占空比= PWM_DATA / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA 数值大于
    PWM_CYCLE 则按 100%处理。
  • 🌿PWM2 输出占空比= PWM_DATA2 / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA2 数值大于
    PWM_CYCLE 则按 100%处理。
🔖实际应用中,建议允许 PWM 引脚输出并且设置 PWM 输出引脚为推挽输出模式。

🍂PWM1 和 PWM2 相关寄存器介绍

在这里插入图片描述

  • 🌿PWM2 数据寄存器(PWM_DATA2):
    在这里插入图片描述
  • 🌿PWM1 数据寄存器(PWM_DATA):
    在这里插入图片描述
  • 🌿PWM 控制寄存器(PWM_CTRL):
    在这里插入图片描述
    在这里插入图片描述
  • 🌿PWM 时钟分频设置寄存器(PWM_CK_SE):
    在这里插入图片描述
  • 🌿PWM 循环周期寄存器(PWM_CYCLE):
    在这里插入图片描述

🌲Timer3 配置图

在这里插入图片描述

🍃PWM3

🌿PWM3利用的是Timer3 的 FIFO 计数器的功能输出对应的占空比。PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END则按 100%处理。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由于PWM3使用了定时3,没有在下面的示例代码中有体现,放在了定时器3的示例代码中。

⛳PWM1和PWM2频率设置方法

- 通过PWM 时钟分频设置寄存器:PWM_CK_SE来设置分频系数,范围0 - 255

🎯PWM引脚映射

  • 📜PWM默认输出引脚:P12P24P25
    在这里插入图片描述
  • 🎉如果使能了PWM映射,那么PWM输出引脚将切换到对应的引脚上。
#define PWMPINAlter( )  { P4_DIR |= bPWM2_ | bPWM1_;PIN_FUNC |= bPWM1_PIN_X;} //设置PWM引脚映射

映射关系

P45 ----> PWM2
P43 ----> PWM1
P42 ----> PWM3

⌛PWM循环周期

🌿通过PWM 循环周期寄存器:PWM_CYCLE 设置,设置范围:0 - 100

🍭PWM1PWM2占空比调节设置

🌿通过PWM1 数据寄存器和PWM2 数据寄存器:PWM_DATA PWM_DATA2。支持范围 0%到 100%,如果PWM_DATA、 PWM_DATA2 数值大于PWM_CYCLE 则按 100%处理。

📖PWM1PWM2输出示例

🌿PWM1PWM2输出频率为500Hz,占比0%-99%递增、递减输出。
  • 时钟采用的是内部时钟:12MHz
/********************************** (C) COPYRIGHT *******************************
* File Name          : PWM.C
* Author             : WCH
* Version            : V1.3
* Date               : 2016/6/24
* Description        : CH559 PWM接口函数  
PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END
则按 100%处理。
PWM1 输出占空比= PWM_DATA / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA 数值大于
PWM_CYCLE 则按 100%处理。
PWM2 输出占空比= PWM_DATA2 / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA2 数值大于
PWM_CYCLE 则按 100%处理。
实际应用中,建议允许 PWM 引脚输出并且设置 PWM 输出引脚为推挽输出模式。
*******************************************************************************/
#include "..\DEBUG.C"                                                         //调试信息打印
#include "..\DEBUG.H"

static UINT8 Duty=5; 
#pragma  NOAREGS

#define SetPWMClk(CK_SE) (PWM_CK_SE = CK_SE) //分频,默认时钟Fsys ,MAX=255           
#define SetPWMCycle(Cycle) (PWM_CYCLE = Cycle)//设置循环周期
#define SetPWM1Dat(dat) (PWM_DATA = dat)  //设置PWM输出占空比
#define SetPWM2Dat(dat) (PWM_DATA2 = dat)
#define PWMPINAlter( )  { P4_DIR |= bPWM2_ | bPWM1_;PIN_FUNC |= bPWM1_PIN_X;} //设置PWM引脚映射

/*******************************************************************************
* Function Name  : InitPWM1(UINT8 polar)
* Description    : PWM1初始化函数
* Input          : polar=0选择默认低电平,高电平输出有效;
                   polar=1选择默认高电平,低电平输出有效;
* Output         : None
* Return         : None
*******************************************************************************/
void  InitPWM1(UINT8 polar)
{
    PWM_CTRL &= ~bPWM_CLR_ALL;                                                //清空FIFO和计数                                                      
    PWM_CTRL &= ~bPWM_MOD_MFM;
    PWM_CTRL |=	bPWM_IE_END;                                                  //使能PWM计数周期完成中断
    PWM_CTRL |=	bPWM_OUT_EN;                                                  //PWM1输出使能
    PWM_CTRL  |= bPWM_IF_END;                                                 //清除所有的中断标志
    if(polar){
        PWM_CTRL |= bPWM_POLAR;                                               //低电平有效
    }
    else{
        PWM_CTRL &= ~bPWM_POLAR;                                              //高电平有效  
    }			
}

/*******************************************************************************
* Function Name  : InitPWM2(UINT8 polar)
* Description    : PWM初始化函数
* Input          : polar=0选择默认低电平,高电平输出有效;
                   polar=1选择默认高电平,低电平输出有效;
* Output         : None
* Return         : None
*******************************************************************************/
void  InitPWM2(UINT8 polar)
{
    PWM_CTRL &= ~bPWM_CLR_ALL;                                                //清空FIFO和计数                                                      
    PWM_CTRL &= ~bPWM_MOD_MFM;
    PWM_CTRL |=	bPWM_IE_END;                                                  //使能PWM计数周期完成中断
    PWM_CTRL |= bPWM2_OUT_EN;                                                 //PWM2输出使能	
    PWM_CTRL  |= bPWM_IF_END;                                                 //清除所有的中断标志
    if(polar){
        PWM_CTRL |= bPWM2_POLAR;                                              //低电平有效
    }
    else{
        PWM_CTRL &= ~bPWM2_POLAR;                                             //高电平有效  
    }			
}

/*******************************************************************************
* Function Name  : PWMInterrupt(void)
* Description    : PWM中断服务程序   
*******************************************************************************/
void	PWMInterrupt( void ) interrupt INT_NO_PWM1 using 1                     //PWM1&2中断服务程序,使用寄存器组1
{
    if(PWM_CTRL & bPWM_IF_END)                                                 
    {
			  Duty +=1;
				Duty %=100;
	PWM_DATA = Duty;
	PWM_DATA2 = 100-Duty;
        PWM_CTRL |= bPWM_IF_END;//PWM 循环周期结束中断标志位清零
			printf("PWM1_DATA:%03u ,PWM2_DATA:%03u \n",(UINT16)PWM_DATA,(UINT16)PWM_DATA2);
    }                                                                
}

void main( ) 
{		
//	UINT8 i;
    mDelaymS(30); //上电延时,等待内部晶振稳定,必加 
    CfgFsys( );  
    PORT_CFG &= ~bP2_OC;
    P2_DIR |= bPWM1 | bPWM2;  //P24 P25 开启PWM建议设置引脚为推挽输出	
    
    mInitSTDIO( );                                                             //串口0,可以用于调试
    printf("start ...\n");
#if 0
    PWMPINAlter( ); //引脚映射	
#endif
    SetPWMClk(240);//设置PWM1&2的时钟分频系数为12,f=Fose/240=50KHz,最大分频数:255
    InitPWM1(1);//PWM1初始化,低电平有效
    InitPWM2(0);//PWM2初始化,高电平有效
    SetPWMCycle(100); //设置循环周期f/100,支持范围 0%到 100%
    IE_PWM1 = 1; //使能PWM1中断
	PWM_DATA = Duty;
	PWM_DATA2 = 100-Duty;
//    SetPWM1Dat(Duty);                                                            //PWM1占空比设置50/100
//    SetPWM2Dat(100-Duty);                                                            //PWM1占空比设置50/100
    EA = 1;                                                                    //中断总开关
    while(1){
		}
}


  • 🌿通过逻辑分析仪测得频率
    在这里插入图片描述
  • 🌿通过串口打印实时动态变化的PWM1和PWM2占空比值
    在这里插入图片描述
  • 输出呼吸灯效果
    在这里插入图片描述
  • 🌿如果想输出1KHz的PWM,那么,设置:SetPWMClk(120);即可。
  • 🌿如果想输出10KHz的PWM,那么,设置:SetPWMClk(12);即可。
  • 🌿如果想输出20KHz的PWM,那么,设置:SetPWMClk(6);即可。

🔖如果时钟配置成24MHz,那么对应的输出频率将翻倍。

📝时钟配置函数

/*******************************************************************************
* Function Name  : CfgFsys( )
* Description    : CH559时钟选择和配置函数,默认使用内部晶振12MHz,如果定义了FREQ_SYS可以
                   根据PLL_CFG和CLOCK_CFG配置得到,公式如下:
                   Fsys = (Fosc * ( PLL_CFG & MASK_PLL_MULT ))/(CLOCK_CFG & MASK_SYS_CK_DIV);
                   具体时钟需要自己配置
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
void	CfgFsys( )  
{
#if OSC_EN_XT
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;                                                 
	CLOCK_CFG |= bOSC_EN_XT;                                                   //使能外部晶振
    mDelaymS(10);
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;   
	CLOCK_CFG &= ~bOSC_EN_INT;
	SAFE_MOD = 0x00; 

#else
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;                                                 
 	CLOCK_CFG &= ~MASK_SYS_CK_DIV;
//  CLOCK_CFG |= 6;                                                            //配置系统时钟48MHz
//  CLOCK_CFG |= 8;                                                            //配置系统时钟36MHz
//  CLOCK_CFG |= 10;                                                           //配置系统时钟28.8MHz
//  CLOCK_CFG |= 12; //配置系统时钟24MHz
//  CLOCK_CFG |= 16;                                                           //配置系统时钟18MHz
  CLOCK_CFG |= 24; //内部时钟频率是 12MHz
/*56MHz
// 	CLOCK_CFG &= ~MASK_SYS_CK_DIV;
//  CLOCK_CFG |= 6;                                                            //配置系统时钟56MHz    
    PLL_CFG = 0xFC;
*/	
    SAFE_MOD = 0xFF;                                                           //关闭安全模式  
//  如果修改主频,要同时修改FREQ_SYS,否则会造成延时函数不准
#endif 
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值