中微CMS79F133学习记录(三)PWM

一:简单介绍

        CMS79F133芯片包含一个 10 PWM 模块,可配置为 4 路共用周期、独立占空比的输出 +1 路独立输出,或 2 组互补输出+1 路独立输出。
        PWM0/PWM1,PWM2/PWM3 可配置成带互补的正反向输出,通过将对应的 TRIS 控制位置 0 来将相应的 PWM 引脚配置为输出。
        PWM的操作相对要复杂一些,它的寄存器有很多,但是其实使用过两次就会发现也就那么回事,PWM的计算公式其实也并不复杂,只需要根据官方的用户手册里的公式套入进去即可,多使用两次就熟悉了。

        PWM寄存器操作写顺序

        由于 10 PWM 占空比数值分配在两个寄存器中,在修改占空比时,程序总是先后修改这两个寄存器,为了保证占空比数值的正确性,芯片内部设计了缓存加载功能。操作 10 位占空比数值需严格按照以下顺序进行:
        1)写高 2 位数值,此时高 2 位数值只是写入内部的缓存;
        2)写低 8 位数值,此时完整的 10 位占空比数值被锁存。

        PWM周期

        PWM 周期是通过写 PWMTH PWMTL 寄存器来指定的。
        公式 1 PWM 周期计算公式:
                                                        PWM 周期=[PWMT+1]*Tosc*( CLKDIV 分频值 )
                                                        注:TOSC=1/FOSC
        当 PWM 周期计数器等于 PWMT 时,在下一个递增计数周期中会发生以下 3 个事件:
        ◆ PWM 周期计数器被清零;
        ◆ PWMx 引脚被置 1
        ◆ PWM 新周期值被锁存;
        ◆ PWM 新占空比值被锁存;
        ◆ 产生 PWM 中断标志位。

        PWM占空比

        可通过将一个 10 位值写入以下多个寄存器来指定 PWM 占空比: PWMDxL PWMDxxH
        可以在任何时候写入 PWMDxL PWMDxxH 寄存器,但直到 PWM 周期计数器等于 PWMT (即周期结束)时,占空比的值才被更新到内部锁存器中。
        公式 2 :脉冲宽度计算公式:
                                                        脉冲宽度 = (PWMDx[9:0]+1)*TOSC*( CLKDIV 分频值 )
        公式3 PWM 占空比计算公式:
                                                        占空比= ( PWMDx[9:0]+1)/( PWMT [ 9:0 ] +1)
        PWM 周期和 PWM 占空比在芯片内部都有双重缓冲。这种双重缓冲结构极其重要,可以避免在 PWM 操作过程中产生毛刺。

        系统时钟频率的改变

        PWM 频率只与芯片振荡时钟有关,系统时钟频率发生任何改变都不会影响 PWM 频率。

        这些文字光看可能看不太懂,但是后面结合代码一起就明白了。 

二:PWM

        相关寄存器

        PWMCON0:配置PWM的时钟分频和使能/失能PWM,例程代码配置为PWMCON0=0B00111111,即1分频,使能所有PWM

        

        PWMCON1:配置PWM0和PWM1的引脚,使能/失能PWM0和PWM2的死区功能,配置死区的时钟分频,例程代码配置为PWMCON1=0B00000000,即PWM01位置选择为RB5/RB4,失能死区功能

        

        PWMCON2:配置PWM的输出模式,例程代码配置为PWMCON2=0B00000000,即正常输出

        PWMTL、PWMT4L:配置PWM的周期低8位,其中PWM0-3共用PWMTL,PWM4独立使用PWMT4L,例程代码配置为PWMTL=0x8F        PWMT4L=0x8F        ,即PWM0-4的周期低8位配置为8F

        PWMTH:这个寄存器的值较为复杂,Bit5-Bit4配置PWM4的占空比高2位,Bit3-Bit2配置PWM4的周期高2位,Bit1-Bit0配置PWM0-3的周期高2位,例程代码配置为PWMTH=0B00001101,即PWM4占空比高2位为00,PWM4的周期高2位为11,PWM0-2的周期高2位为01

        PWMD0L、PWMD1L、PWMD2L、PWMD3L、PWMD4L:这5个寄存器是配置PWM0-4的占空比的低8位,例程代码配置为PWMD0L=0x4F        PWMD1L=0x9F        PWMD2L=0xEF        PWMD3L=0x3F        PWMD4L=0xE3        ,即PWM0-4的占低8位配置分别为4F、9F、EF、3F、E3

        PWM01H、PWM23H:配置PWM1-3的占空比高2位,PWM4的占空比高2位在PWMTH里设置过了,例程代码配置为PWMD01H=0x00        PWMD23H=0x10       ,即PWM0-1的占空比高2位都为00,PWM2的占空比高2位为00,PWM2的占空比高2位为01
        需要注意的是,写入PWM的高2位不会立即生效,需要有写入PWM的低8位才会生效

        PWM01DT、PWM23DT:配置PWM0-3的死区时间,例程代码配置为PWM01DT=0x3F        PWM23DT=0        ,即PWM0-1的死区时间配置为3F,PWM2-3的死区时间配置为0

        代码部分

        头文件

#include <cms.h>

        主函数

        TRISB为PORTB的方向寄存器,用来配置PORTB的输入输出,设置为0代表配置PORTB的所有引脚为输出

void main()
{
	asm("nop");
	asm("clrwdt");
	
	OSCCON = 0X71;				//内部振荡器用作系统时钟
	
	TRISB = 0;					//配置PWM引脚为输出脚
	
	Set_PWM();				//设置PWM周期50us,占空比PWM0-20%、PWM1-40%、PWM2-60%、PWM3-80%、PWM4-50%
	
	while(1)
	{
		asm("clrwdt");
	}
}

        PWM部分

        PWMTL = 0x8f;
        PWMT4L = 0x8f;
        PWMTH = 0B00001101;

        这部分是配置PWM0-4的周期低8位和高2位,还有PWM4的占空比高2位

        中间部分代码以PWM0为例,PWM0的占空比高2位是00,低8位是0100 1111,即0x04F,十进制为79,PWM0的周期高2位是01,低8位是1000 1111,即0x18F,十进制为399,根据公式3占空比=(PWMDx[9:0]+1)/(PWMT[9:0]+1),可以计算出占空比为(79+1)/(399+1)=20%,PWM1-4的计算方式同理 

        死区部分代码可以看到PWM01DT的值为0x3F,根据死区宽度 = (PWMxDT[5:0]+1)*TOSC*(DT_DIV分频值),TOSC=1/FOSC,可以计算出死区宽度为(63+1)x(1/16)x1=4us

        最后部分的代码则是配置PWM为正常输出模式,选择PWM01的输出脚,失能PWM0-4死区,PWM分频为Fosc/2,使能所有PWM

void Set_PWM()
{
	PWMTL = 0x8f;					//PWM0~3共周期,周期低位
	PWMT4L = 0x8f;					//PWM4独立周期,周期低位		
	PWMTH = 0B00001101;				//周期高两位及PWM4占空比高两位	

									//PWM0~3周期为:(0B110001111+1)*(1/16)*2 =50uS
									//PWM4周期为:(0B1110001111+1)*(1/16)*2 =114uS		
	
	PWMD01H = 0x00;					//高位改变后不能立即生效,需要给占空比的低位寄存器后才能加载
	//PWM0 占空比设置为20%
	PWMD0L = 0x4F;					//(79+1)/(399+1) = 20%
	//PWM1 占空比设置为40%
	PWMD1L = 0x9F;					//(159+1)/(399+1) = 40%

	PWMD23H = 0x10;
	//PWM2 占空比设置为60%
	PWMD2L = 0xEF;					//(239+1)/(399+1) = 60%
	//PWM3 占空比设置为80%
	PWMD3L = 0x3F;					//(319+1)/(399+1) = 80%

	//PWM4 占空比设置为25%
	PWMD4L = 0xE3;					//(227+1)/(911+1) = 25%
	
	
	PWM01DT = 0x3F;					//死区时间,低6位有效位=(0B00111111+1)*(1/16)*1 =4uS
	PWM23DT = 0;
	
	PWMCON2 = 0B00000000;			//正常输出
	PWMCON1 = 0B00000000;			//PWM01位置选择为RB5/RB4;禁止死区;可使能PWM0/1互补,PWM2/3互补
	PWMCON0 = 0B00111111;			//PWM分频Fosc/2,使能PWM0、PWM1、PWM2、PWM3、PWM4
}

  • 27
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值