赞
踩
目录
PWM的全称是脉冲宽度调制(Pulse-width modulation),是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式,幅值、周期(或频率)不变,脉宽(或占空比)可调的脉冲波。
T:脉冲周期;
f:脉冲频率,f = 1 / T;
W:脉冲宽度,简称“脉宽”,是脉冲高电平持续的时间;
占空比 = Ton /(Ton+Toff)= Ton / T。
如果我们想要控制一个直流电机的转速,我们可以通过改变其两端电压即可;但是该种方法有很大的局限性,可调直流电源构造复杂、成本高昂,应用起来很不现实。所以我们采用另外的控制方式:电压源→驱动器→直流电机,电压源提供直流电压,不同的驱动器控制不同的直流电机,应用非常灵活。其中驱动器对电机的调速控制就是利用PWM。
如图,电机为某相同转速时,红色代表驱动器输出幅值不变的PWM波,蓝色代表可调直流电源输出的电压。两者都是直接作用到负载。
①当PWM波的占空比越大时,所对应的直流电压与PWM波的幅值越接近;反之与0V越接近;
②周期的红色PWM波脉宽下的矩形面积之和与蓝色直流电压的面积相等,即伏秒积相等:U红(幅值) × Ton = U蓝 × T;
例如当PWM波的幅值为24V,占空比为50%时,与直流电压12V作用到电机上所产生的效果是一模一样的,即速度相同;即24V×50%=12V。 PWM波的频率不可随意,频率太低会导致电机运转不畅,振动大,噪音大;频率太高会导致驱动器开关损耗较大,甚至有电机会啸叫而不转的情况。一般1K~30K的PWM频率较为普遍。
PWM实现的原理是通过锯齿波/三角波(载波)所需要合成的波形(调制波)进行比较,然后确定PWM所需要输出的极性,通常是高电平或者是低电平,因为一般都是作用到开关元器件上;如下图所示。
振荡器输出的锯齿波和参考值 进行比较,然后就可以输出PWM波形了;
软件模拟PWM产生,一般采用定时器实现,使用定时器控制GPIO口的高电平和低电平的翻转时间即可实现输出方波的频率控制和占空比控制。软件模拟PWM常应用于实时性要求不高,频率要求不高的场合。如下是软件模拟PWM实现代码。
- #include "STC8H.h"
- #include "intrins.h"
-
- #define PWM5_1 0x00 //P2.0
- #define PWM5_2 0x01 //P1.7
- #define PWM5_3 0x02 //P0.0
- #define PWM5_4 0x03 //P7.4
-
- #define PWM6_1 0x00 //P2.1
- #define PWM6_2 0x04 //P5.4
- #define PWM6_3 0x08 //P0.1
- #define PWM6_4 0x0C //P7.5
-
- #define PWM7_1 0x00 //P2.2
- #define PWM7_2 0x10 //P3.3
- #define PWM7_3 0x20 //P0.2
- #define PWM7_4 0x30 //P7.6
-
- #define ENO5P 0x01
- #define ENO6P 0x04
- #define ENO7P 0x10
-
- #define PWM_PERIOD 1020 //设置周期值
-
- unsigned int adc3 = 0;
- unsigned int PWM5_Duty = 1021;
- unsigned int PWM6_Duty = 1021;
- unsigned int PWM7_Duty = 1021;
-
- void soft_delay(unsigned int ms)
- {
- unsigned int i,j;
- for(i = 0;i < ms;i++)
- for(j = 0;j < 200;j++);
- }
-
- /*主函数*/
- void main(void)
- {
-
- P1M1 = 0X08; P1M0 = 0X00; //设置P13为ADC口
- P_SW2 |= 0x80;
- ADCTIM = 0x3f; //设置ADC内部时序
- P_SW2 &= 0x7f;
- ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16
- ADC_CONTR = 0x83; //使能ADC模块,使能ADC3
-
- P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
- P7M1 = 0x8f;P7M0 = 0x70; //设置为准双向口
-
- PWMB_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道
- PWMB_CCER2 = 0x00;
- PWMB_CCMR1 = 0x68; //通道模式配置
- PWMB_CCMR2 = 0x68;
- PWMB_CCMR3 = 0x68;
- PWMB_CCMR4 = 0x68;
- PWMB_CCER1 = 0x33; //配置通道输出使能和极性
- PWMB_CCER2 = 0x33;
-
- PWMB_ARRH = (unsigned char)(PWM_PERIOD >> 8); //设置周期时间
- PWMB_ARRL = (unsigned char)PWM_PERIOD;
-
- PWMB_ENO = 0x00;
- PWMB_ENO |= ENO5P; //使能输出
- PWMB_ENO |= ENO6P; //使能输出
- PWMB_ENO |= ENO7P; //使能输出
-
- PWMB_PS = 0x00; //高级 PWM 通道输出脚选择位
- PWMB_PS |= PWM5_4; //选择 PWM5_4 通道
- PWMB_PS |= PWM6_4; //选择 PWM6_4 通道
- PWMB_PS |= PWM7_4; //选择 PWM7_4 通道
-
- PWMB_BKR = 0x80; //使能主输出
- PWMB_CR1 |= 0x01; //开始计时
-
- PWMB_CCR5H = (unsigned char)(PWM5_Duty >> 8); //设置占空比时间
- PWMB_CCR5L = (unsigned char)(PWM5_Duty);
- PWMB_CCR6H = (unsigned char)(PWM6_Duty >> 8); //设置占空比时间
- PWMB_CCR6L = (unsigned char)(PWM6_Duty);
- PWMB_CCR7H = (unsigned char)(PWM7_Duty >> 8); //设置占空比时间
- PWMB_CCR7L = (unsigned char)(PWM7_Duty);
-
- while(1)
- {
- ADC_CONTR |= 0x40; //启动AD转换
- _nop_();
- _nop_();
- while (!(ADC_CONTR & 0x20)); //查询ADC完成标志
- ADC_CONTR &= ~0x20; //清完成标志
- adc3 = ADC_RES; //读取ADC结果
- PWMB_CCR7H = (unsigned char)((adc3*4) >> 8); //设置占空比时间
- PWMB_CCR7L = (unsigned char)(adc3*4)+1;
- soft_delay(2);
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。