一、概述:
STC8H系列单片机的16位高级PWM定时器是STC各类单片机PWM控制功能最强的系列之一,当然也是控制最复杂的单片机系列。通过控制内部16位定时器和时钟系统可以对外输出任意频率和占空比的PWM波,以下的呼吸灯就是一个PWM波输出案例,高速输出的PWM波通过改变波形的占空比,实现LED灯不同亮度的显示。高级PWM的PWMA组可以输出互补/对称/带死区控制的PWM波,这一项功能是特别针对无刷电机控制定制的功能,通过对称输出实现H桥的控制达到变频输出的目的。此外还可捕获上升、下降沿,测量波形的周期、占空比值,及脉冲宽度等等。
二、知识链接:
1、时基单元:
CK_PSC为时钟源,过分频器后得到CK_CNT用来计数,PWMA_ARR用来控制脉冲的周期,PWMA_CNTR用来计数。
当计数器的值到达PWMA_ARR时,计数器的值清零,又重新开始计数。
关于时钟源CK_PSC的来源有4种来源,通过PWMA_SMCR的SMS位控制,其中ECE为外部时钟使能,当使用外部时钟模式时即必须将ECE置1。
2、PWM模式:
当PWMA_CR寄存器中的DIR=0时,执行向上计数。
当PWMA_CNT< PWMA_CCR1时,PWM输出高电平,否则输出低电平。
3、高级PWM功能脚的切换:
以下的实例开启P1.0与P1.1作为PWMA通道1输出端
4、输出使能端:
开启EON1P位置1(P1.1)与开启EON1N位置1(P1.2)
5、捕获比较使能寄存器:
开启CCINE=1和CC1E=1使能PWMA通道1比较器工作。
6、捕获比较模式寄存器:
选择OC1M=110为PWM模式1,OC1PE=1开启PWM的预装功能:
7、频率计算:
例如:当SYSclk=12M=12000000Hz时,求占求比为1/2,50Hz的PWM频率输出,计算各寄存器的配置能数PWMA_PSCR分频值,PWMA_ARR周期值,PWMA_CRR的占空比值。
解:
1、求出分频倍数
12000000/50=240000
2、求出组合分频:
(PWMA_PSCR+1)*( PWMA_ARR+1)=(3+1)*(59999+1)
PWMA_PSCR=0x0003
PWMA_ARR=0xEA5F
3、求出占空比的值:
PWMA_CRR=1/2*59999=0x752F
三、实验平台搭建:
1、MCU:STC-打狗棒系列核心实验板 V2.3
2、实验板平台:德飞莱LY-51s
3、硬件连接表:
P10---------->LED1
P11---------->LED2
四、测试源代码:
#include <STC8H.h>
#include "intrins.h"
void Delay1ms(unsigned char x);//当主时钟频率为12M,1ms延时为基准
void init_IO();//初始化IO
void init_PWM();
void main()
{
unsigned char i=0;
P_SW2 |= 0x80; //扩展寄存器XFR访问使能
init_IO();
init_PWM();
while(1)
{
i=0;
//LED由亮到暗
for(i=0;i<=254;i++)
{
Delay1ms(20);
PWMA_CCR1L = i;
}
//LED由暗到亮
for(i=254;i>0;i--)
{
Delay1ms(20);
PWMA_CCR1L = i;
}
}
}
void init_IO()
{
RSTCFG=0x50; //开启RST键进入ISP模式
P0M1 = 0x00; P0M0 = 0x00; //设置P0口为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置P1口为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置P5口为准双向口
}
void init_PWM()
{
PWMA_CCMR1 = 0x68;
PWMA_CCER1 = 0x55;
PWMA_PSCRH=0x00;
PWMA_PSCRL=0xB7;
PWMA_ARRH = 0x00; //设置周期时间
PWMA_ARRL = 0xff;
// PWMA_ARRH = 0xFF; //设置周期时间
// PWMA_ARRL = 0xFF;
PWMA_ENO |= 0x01; //使能输出
PWMA_ENO |= 0x02; //使能输出
PWMA_PS = 0x00; //高级 PWM 通道输出脚选择位
PWMA_BKR = 0x80; //使能主输出
PWMA_CR1 |= 0x01; //开始计时
PWMA_CCR1H = 0x00; //设置占空比时间
PWMA_CCR1L = 0x00;
// PWMA_CCR1H = 0x3F; //设置占空比时间
// PWMA_CCR1L = 0xFF;
}
void Delay1ms(unsigned char x) //@12.000MHz
{
unsigned char i, j;
while(x--)
{
i = 16;
j = 147;
do
{
while (--j);
} while (--i);
}
}