STC8H系列单片机PWM基础知识入门教程(五)

目录

一、PWM概念

二、电机控制原理

三、硬件PWM实现原理 

四、软件PWM产生原理

五、示例代码


一、PWM概念

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波形了;

四、软件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);
	}
}

作者:芯航路IOT

物联沃分享整理
物联沃-IOTWORD物联网 » STC8H系列单片机PWM基础知识入门教程(五)

发表评论