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);
	}
}

### STC8H1K08 单片机 PWM 功能使用教程 #### 配置方法概述 STC8H1K08是一款高性能的8单片机,内置丰富的外设资源,其中包括多个PWM通道。为了实现PWM功能,通常需要配置定时器以及相应的PWM寄存器。 #### 定时器配置 对于STC8H1K08而言,在使用PWM之前需先设置好定时器模式。根据具体需求可以选择不同的工作方式,比如Timer 0可以被设定为自动重装载模式下的16位计数器[^3]: ```c void Timer0_Init(void) { TMOD &= 0xF0; // 清除原有设置 TMOD |= 0x01; // 设置为Mode 1 (16-bit timer) TH0 = TL0 = 0xFF; // 初始值预设,用于调整周期长度 ET0 = 1; // 开启中断使能 EA = 1; // 打开总中断 } ``` #### 初始化PWM模块 接下来就是针对特定PWM通道的具体初始化操作了。这里以通用型PWM为例说明如何开启并调节其输出特性[^1]: ```c #include "stc8h1k08.h" // 假定我们正在处理的是CH0A/B这一对互补输出端口 void Init_PWM(void){ PCONP |= PCPWMEN; // 启用PWM控制器电源管理控制位 PWMPRCLKSEL=0b00; // 设定分频系数,默认不分频 PWMMODE|=PWMMODEM0|PWMMODEM1;//选择匹配模式 PWMLAR=255; // 设置低字节比较值 PWMUAR=255; // 设置高字节比较值 PWMPOL|=PWMPOLA0; // 输出极性反转(可选) PWME|=PWMENA0; // 允许对应PWM通道输出 } ``` #### 更新占空比 值得注意的是,在某些情况下即使完成了上述两步也可能遇到LED亮度不变等问题。这可能是由于缺少必要的刷新机制所致。因此还需要调用专门设计好的`UpdatePwm()`函数来手动触发一次即时更新动作[^2]: ```c typedef struct { u16 duty; } PWMx_Duty; void UpdatePwm(u8 PWM, PWMx_Duty *PWMx) { switch(PWM){ case CH0: PWMDTYL=PWMx->duty&0xff; PWMDTYH=(PWMx->duty>>8)&0xff; break; default : ; } } int main(){ ... while(1){ static PWMx_Duty pwm_duty={127}; // 中间位置作为初始状态 UpdatePwm(CH0,&pwm_duty); delay_ms(10); // 添加适当延时 if(some_condition){ // 根据实际应用场景修改条件判断语句 pwm_duty.duty+=some_value; }else{ pwm_duty.duty-=another_value; } } } ``` 通过以上步骤即可成功地在STC8H1K08上实现基础版PWM输出,并能够灵活调控输出波形的各项参数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芯航路IOT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值