PWM就是个脉冲波高电平时间占满就是满PWM相当于P1^0 = 1;当低电平时间占满时等效与
P1^0 = 0 ;多用于电机驱动(小白只用过这个功能🤣)。STC8A8K64D4单片机自带PWM功能
寄存器 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
PWMSET | F1H | - | PWMRST | - | - | - | - | - | ENPWM |
ENPWM:PWM使能位(使能/失能PWM通道)
0:失能PWM
1:使能PWM
使用PWMnCR寄存器配置其引脚例子如下表
寄存器 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
PWM0CR | FF14H | ENO | INI | - | C0_S[1:0] | ENI | ENT2I | ENT1I |
ENO:PWM输出使能位 0:失能通道端口为GPIO口。1:使能通道端口为PWM输出口
INI:PWM的初始电平 因为PWM是有两个触发点当到第一个触发点时是低电平。此时初始电平设置为低电平波形会受到影响。0:PWM初始电平低电平。1:PWM初始电平高电平。
C0_S[1:0]:PWM通道0引脚选择 一个通道有多个引脚选择但是只能使用一个引脚作为输出引脚使用。
ENI :PWM通道中断使能 0:失能PWM通道中断 1:使能PWM通道中断
ENT2I:PWM通道在第二个触发点的中断控制位
0:失能PWM通道第二个触发点的中断 1:使能PWM通道第二个触发点中断
ENT1I:PWM通道在第一个触发点的中断控制位
0:失能PWM通道第一个触点中断 1:使能PWM通道第一个触发点中断
寄存器 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
PWMCKS | FF02H | - | - | - | SELT2 | PWM_PS[3:0] |
SELT2:PWM时钟源选择 。
0:PWM时钟源为系统分频时钟 1:PWM时钟源为定时器2溢出脉冲
PWM_PS[3:0]:系统时钟预分频参数
SELT2 | PWM_PS[3:0] | PWM输入时钟源频率 |
1 | 分频没用 | 定时器2溢出脉冲 |
0 | 0000 | SYSclk/1 (1分频) |
0 | 0001 | SYSclk/2 (2分频) |
0 | 0010 | SYSclk/3 (3分频) |
PWM占空比寄存器(CCR)PWMC
在STC8A8K中PWM只能向上计数所以CCR的值为一个PWM周期的数,PWMC是15位寄存器。
PWMCH:PWM计数器高7位
PWMCL:PWM计数器低8位
值设定位1~32767。当内部计数器的值计数到PWMC设定的值时PWM值会从0开始计数
时钟源 | PWM输出频率计算公式 |
SELT2 = 0 | PWM输出频率= SYSclk / ( (PWM_PS + 1) * (PWMC + 1) ) |
SELT2 = 1 | PWM输出频率= SYSclk / (PWMC + 1) |
例如:输出一个1ms的PWM 单片机自带的晶振是24MHz 分频为2分频 根据公式可得 (PWMC + 1) = 12000 PWMC = 11999 ;
PWM占空比配置寄存器:
第一触发点:PWMnT1H低7位和PWMnT1L组成15位的计数器。
第二触发点:PWMnT2H低7位和PWMnT2L组成15位的计数器。
PWM配置寄存器(PWMCFG)
寄存器 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
PWMCFG | F6H | - | - | - | - | PWMCBIF | PWMCBI | ENPWMTA | PWMCEN |
PWMCBIF:PWM计数器归零中断标志位
当15位计数器记满溢出归零时,硬件自动置一,并发送中断请求,需要软件置零。
PWMCBI:PWM计数归零中断使能
0:失能PWM计数器归零中断,但是PWMCBIF依旧会置一
1:使能PWM计数器归零中断。
ENPWMTA:是否与ADC相关
0:不相关 1:相关
PWMCEN:计数开始位
0:PWM停止计数 1:开始计数
注意:PWMCEN开启后立即开始计数所以放在最后开启
接下来配置PWM的初始化函数
void pwm_config(void)
{
PWMSET |= 0x01; //先使能PWM
PWMCFG = 0x04; //计数器溢出标志位清零 使能PWM归零中断 PWMADC不关联
P_SW2 |= 0x80; //访问特殊功能寄存器
PWMCKS = 0x0B; //时钟选择系统时钟,时钟分频12
PWM6CR = 0xC0; //通道6PWM使能 初始电平配置 和通道引脚选择
PWMC = 1999;
PWM6T1 = 0; //第一触发点
PWM6T2 = 0x0001; //第二触发点
P_SW2 &= 0x7F; //关闭特殊功能寄存器配置
PWMCFG |= 0x01; //开启PWM计数开始
}
当PWM运行完一个周期后会进入PWM中断中在对第二触发点的值进行更改就可以改变其占空比
void pwm_isr(void) interrupt 22 using 1
{
static bit bright_flag = 1;
static unsigned int pwm_strength = 0 ;
if( PWMCFG & 0x08 )
{
if(bright_flag == 1)
{
pwm_strength++;
if( pwm_strength >= CYCLE_VALUE )
{bright_flag = 0;}
}
if(bright_flag == 0)
{
pwm_strength--;
if(pwm_strength <= 0)
{bright_flag = 1;}
}
PWMCFG |= ~0x08;
}
P_SW2 |= 0x80;
PWM6T2 = pwm_strength;
P_SW2 &= 0x7F;
delay_ms(1);
}