使用STC12单片机设置50Hz PWM波驱动舵机
本文将使用STC12C5A60S2配置PWM波,驱动SG90舵机。
采用的开发板包括了CH340芯片,因此下载程序只需要使用MicroUSB转USB连接线使用STC-ISP.exe软件下载程序即可。
1 芯片资源
芯片型号STC12C5A60S2,增强型8051 CPU,1T,单时钟/机器周期,指令代码兼容传统8051,工作电压5.5V-3.5V,工作频率范围0-35MHz,共有4个16位定时器(包括2个16位定时器T0和T1,2路PCA模块实现2个16为定时器),拥有2路PWM(PCA的PWM模式)。
2 舵机控制信号
舵机分为三根线,包括:VCC(5V)、GND和PWM。
PWM波的信号频率在50Hz左右,高电平占空比为2.5%-12.5%,也就是一个周期20ms,高电平占0.5-2.5ms。
2 STC12设置PCA的PWM模式
STC12C5A60S2系列单片机集成了两路可编程计数器阵列(PCA)模块,可用于软件定时器、外部脉冲的捕捉、高速输出以及脉宽调制(PWM)输出。
PCA可以控制2路PWM波。
相关寄存器列表:
寄存器名称 | 功能 |
---|---|
CCON | PCA控制寄存器 |
CMOD | PCA模式寄存器 |
CCAPM0 | PCA模块模式0寄存器 |
CCAPM1 | PCA模块模式1寄存器 |
CL | CPA基位定时器低位(PCA Base Timer Low) |
CH | CPA基位定时器高位(PCA Base Timer High) |
CCAP0L | PCA模块0捕获寄存器低位 |
CCAP0H | PCA模块0捕获寄存器高位 |
CCAP1L | PCA模块1捕获寄存器低位 |
CCAP1H | PCA模块1捕获寄存器高位 |
PCA_PWM0 | PCA PWM模式辅助寄存器0 |
PCA_PWM1 | PCA PWM模式辅助寄存器1 |
AUXR1 | 辅助寄存器1(能够设置输出引脚) |
2.1 CCON:PCA控制寄存器
功能:控制PCA溢出标志位、控制PCA运行状态。PCA模块0和1的中断标志。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
CCON | 0xD8 | CF | CR | – | – | – | – | CCF1 | CCF0 |
2.2 CMOD:PCA工作模式寄存器
功能:控制空闲模式PCA计数状态、PCA计数脉冲源选项、PCA溢出中断使能。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
CMOD | 0xD9 | CIDL | – | – | – | CPS2 | CPS1 | CPS0 | ECF |
CIDL和ECF在此不做介绍,主要介绍CPSn的PCA计数脉冲源选择控制位。
CPS2 | CPS1 | CPS0 | 选择PCA时钟源输入 |
---|---|---|---|
0 | 0 | 0 | 0,SYSCLK/12 |
0 | 0 | 1 | 1,SYSCLK/2 |
0 | 1 | 0 | 2,定时器0的溢出脉冲。通过改变定时器0的分频率,能够实现SYSCLK的1-256分频。 |
0 | 1 | 1 | 3,ECI/P1.2(或P4.1)脚输入的外部时钟(最大速率为SYSCLK/2) |
1 | 0 | 0 | 4,SYSCLK |
1 | 0 | 1 | 5,SYSCLK/4 |
1 | 1 | 0 | 6,SYSCLK/6 |
1 | 1 | 1 | 7,SYSCLK/8 |
但PWM频率不等于PCA频率,PWM波由于要控制占空比,因此每256个PCA周期设置为1个PWM波周期,一部分高电平、一部分低电平。PWM频率=PCA频率/256。
本文主要关注定时器0溢出脉冲输入PCA。
2.3 CCAPM0:PCA比较/捕获寄存器
PCA模块0的比较/捕获寄存器。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
CCAPM0 | 0xDA | – | ECOM0 | CAPP0 | CAPN0 | MAT0 | TOG0 | PWM0 | ECCF0 |
模式设置:
由于需要使用PWM模式输出,无需中断,所以CCAPM0=0x42。
2.4 CL、CH:PCA的16位计数器
CL为低8位计数器,CH为高8位计数器。
CL和CH用来保存PCA的装载值,复位值为0x00。
2.5 CCAP0L、CCAP0H:PCA捕获/比较寄存器
CCAP0L为低位字节、CCAP0H为高位字节。当PCA模块用于捕获或比较时,他们用于保存各个模块的16位捕捉计数值。当PCA模块用于PWM模式时,他们用来控制输出的占空比。 复位值均为0x00。
2.6 AUXR1:辅助寄存器引脚功能
辅助寄存器1将单片机的PCA/PWM功能从P1口设置到P4口。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
AUXR1 | 0xA2 | – | PCA_P4 | SPI_P4 | S2_P4 | GF2 | ADRJ | – | DPS |
3 STC12设置定时器0
3.1 TCON:定时器/计数器控制寄存器
TCON为定时器/计数器T0、T1的控制寄存器,同时也锁存T0、T1溢出中断源和外部请求中断源。本文内只需要T0。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
TCON | 0x88 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
3.2 TMOD:定时器/计数器工作模式寄存器
定时和计数功能由特殊功能寄存器TMOD的控制位C/T进行选择。
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
TMOD | 0x89 | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
B7-B4为定时器1的控制位,B3-B0为定时器0的控制位。
M1 | M0 | 功能 |
---|---|---|
0 | 0 | 13位定时器/计数器,兼容8048定时模式,TL0只用低5位参与分频,TH0整个8位全用。 |
0 | 1 | 16位定时器/计数器,TL0、TH0全用 |
1 | 0 | 8位自动重装载定时器,当溢出时将TH0存放的值自动重装入TL0 |
1 | 1 | 定时器0此时作为双8位定时器/计数器。TL0作为一个8位定时器/计数器,通过标准定时器0的控制位控制。YH0仅作为一个8位定时器,由定时器1的控制位控制。 |
3.3 TL0、TH0
此寄存器用于控制PWM的占空比。
3.4 AUXR:辅助寄存器
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
AUXR | 0x8E | T0x12 | T1x12 | UART_M0x6 | BRTR | S2SMOD | BRTx12 | EXTRAM | S1BRS |
3.5 WAKE_CLKO:时钟输出和掉电唤醒寄存器
寄存器名称 | 地址 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|
WAKE_CLKO | 0x8F | PCAWAKEUP | RXD_PIN_IE | T1_PIN_IE | T0_PIN_IE | LVD_WAKE | BRTCLKO | T1CLKO | T0CLKO |
4 定时器T0与PWM配置思路
芯片晶振频率为11.0592MHz,输入芯片内得到SYSCLK=11059200Hz。
由于PWM波需要50Hz,PCA将一个周期时长固定划分为256个部分,因此PWM波频率=PCA输入频率/256。
所以PCA输入频率为50*256=12800Hz。
CMOD寄存器中可以设置PCA的输入模式,输入模式分为8种,可以对SYSCLK脉冲、T0溢出脉冲进行分频。
由于SYSCLK/12=11059200/12=921600Hz,远大于PCA输入频率12800Hz,输入模式:0、1、3、4、5、6、7都无法完成分频。因此需要采用输入模式2:定时器0计数溢出脉冲,在1T情况下,分频能够达到SYSCLK/num,num可以为1~256。
芯片有1T模式和12T模式,12T模式是12个周期执行一条指令,兼容8051。
定时器0如果设置为1T模式,采用最大的分频数256,能够输入到PCA的最小频率为SYSCLK/256=11059200/256=43200Hz,也无法满足12800Hz的要求。
因此必须采用12T模式,先将SYSCLK进行12分频,得到频率SYSCLK/12=11059200/12=92600Hz,然后再在定时器0中得到分频。
如图所示,定时器T0采用12T模式(T0x12=0或AUXR.7=0)、定时器(C/T-=0或TMOD.2=0)、模式2:8为自动重载定时器(M1/M0=1/0或TMOD.1/0=1/0)、关闭外部输入(GATE=0或TMOD.3=0)、打开定时器运行控制位(TR0=1或TCON.5=1)。
TL0和TH0都是8位寄存器,两个都通过软件设置相同的值,当TL0捕获到左侧传来的脉冲,从设置好的值到255逐渐递增,然后溢出,这就是定时器的分频过程。计时器T0的溢出脉冲为PCA提供输入信号,同时TH0也会将存储的值传递给TL0,以便进行下一次分频。
上文已经得出输入定时器频率为921600Hz,如果想通过分频得到PCA所需的12800Hz频率,需要分进行921600/12800=72分频。
因此设置定时器0的两个寄存器TL0和TH0为256-72=184。
小结:
1、晶振频率11059200Hz。
2、定时器0采用12T预先分频,得到11059200/12=921600Hz。
3、定时器0设置TL0=TH0=256-72=184,为72分频,得到定时器0溢出频率921600/72=12800Hz。
4、定时器0溢出频率输入到PCA内,PWM波频率为12800/256=50Hz。
5、修改PWM波占空比,设置CCP0L=CCP0H=n(0<n<256),n越大,占空比Duty越大,从0%-100%。
代码如下:
#include "reg51.h"
#include "intrins.h"
/*Declare SFR associated with the PCA */
sfr CCON = 0xD8; //PCA control register
sbit CCF0 = CCON^0; //PCA module-0 interrupt flag
sbit CCF1 = CCON^1; //PCA module-1 interrupt flag
sbit CR = CCON^6; //PCA timer run control bit
sbit CF = CCON^7; //PCA timer overflow flag
sfr CMOD = 0xD9; //PCA mode register
sfr CL = 0xE9; //PCA base timer LOW
sfr CH = 0xF9; //PCA base timer HIGH
sfr CCAPM0 = 0xDA; //PCA module-0 mode register
sfr CCAP0L = 0xEA; //PCA module-0 capture register LOW
sfr CCAP0H = 0xFA; //PCA module-0 capture register HIGH
sfr CCAPM1 = 0xDB; //PCA module-1 mode register
sfr CCAP1L = 0xEB; //PCA module-1 capture register LOW
sfr CCAP1H = 0xFB; //PCA module-1 capture register HIGH
sfr PCAPWM0 = 0xf2;
sfr PCAPWM1 = 0xf3;
sfr AUXR = 0x8E;
sfr WAKE_CLKO = 0x8F;
void Timer0_Init(int i);
void PWM_Init(int i ,int j);
void PWM_Config(float duty);
void delay_ms(int num);
void main()
{
// 初始化定时器0,确定溢出频率
Timer0_Init(50);
// 初始化PWM外设
PWM_Init(0x04,0x42);
while(1)
{
// 设置占空比
PWM_Config(12.5);
delay_ms(256);
// 设置占空比
PWM_Config(10);
delay_ms(256);
// 设置占空比
PWM_Config(7.5);
delay_ms(256);
// 设置占空比
PWM_Config(5);
delay_ms(256);
// 设置占空比
PWM_Config(2.5);
delay_ms(256);
}
}
// i为PWM波频率
void Timer0_Init(int i)
{
int j = 0;
// int k = 0;
// k = i * 256; // 定时器0输出的溢出脉冲,输入到PCA的频率
j = (int)(3600/i); // 定时器0分频数(11059200/12 /i /256 = 3600/i)
EA = 0; // 禁止中断
TMOD |= 0x02; // 配置为八位自动重装载
AUXR |= 0x00; // 12T模式,SYSCLK/12=11059200/12=921600Hz
TL0 = 256-j;
TH0 = 256-j; // 原来是256-j
TR0 = 1; // 启动计数器计数
TF0 = 0; // 清空溢出标志位
WAKE_CLKO = 0x01;
}
void PWM_Init(int i,int j)
{
CL = 0x00;
CH = 0x00;
CMOD = i;
CCAPM0 = j; // 使用比较功能,脉宽调节模式
CR = 1; // 启动PCA计数器
}
void PWM_Config(float duty) // 范围为2.5-12.5
{
int width = 0;
width = (int)(duty*2.56);//-1+0.5;
// duty写的是12.5,实际是12.5%,需要duty/100*256
CCAP0H = 256-width;
CCAP0L = CCAP0H;
}
void delay_ms(int num)
{
int i,j;
for(i=0; i<num;i++){
for(j=0; j<2560;j++);
}
}
作者:阳排