基于51单片机T2的高精度PWM控制舵机
2025-09-23 来源:bilibili
摘 要
虽然舵机的控制原理比较简单统一,但是PWM控制舵机的程序实现方式多种多样,有的使用延时(delay(ms)),有的使用定时器(time),而网上搜到的大部分控制代码却质量一般,控制精度都需要提高,就要对单片机定时器有详细的了解,否则延时将出现偏差。
本文使用单片机T2定时器,这个定时器大多数人很少使用它,而却不知道它有一个非常优秀的功能就是定时自动重载功能。利用这个功能能够更为精确的对定时器进行设定,可控制精度在1个机器周期(12M晶振下就是1us),T0、T1都需要手动重载,其精度无法很好的控制。
本程序硬件需求
/*------------------------------硬件需求: 12T系列单片机(8051内核) 拥有T2定时器 12M时钟晶振 P2_0输出控制 舵机角度范围在0~180 高电平范围0.5ms~2.5ms 20ms周期 --------------------------------*/
软件仿真演示(精准的50Hz的PWM信号)

程序设计思想:
根据舵机对PWM的需求,我们可以得知在20ms的周期中,我们需要在输出开始为高电平,在高电平结束时触发中断改为低电平,低电平结束后由触发中断将其设置为输出高电平,如此循环往复。
其中我们可以发现,我们的定时器是不断根据角度的设定而变化的,而定时器的工作需要在计时高电平与低电平间来回切换,这个定时器定时下次时间是通过装载在RCAP中的初始值决定了,于是我们完全可以通过设定RCAP2L,RCAP2H来改变下一次的定时时间,根据这个思想 定时器中断中便如此设计。
if(SW)的分支语句 将20ms分为高低电平的定时 而且可以确定两者之和是20ms 也就是说完成了20ms的周期PWM波的输出。

具体功能见代码 ,注释,有问题请在评论区留言
// Header:PWM舵机控制程序
// File Name:
// Author:程蒙蒙(QQ1058515967)
// Date:2018年9月12日
//Description:基于12T系列单片机且有T2定时器的单片机舵机控制程序
//,本程序控制精度高(1us),定时器自动控制舵机转动
/*------------------------------
硬件需求: 12T系列单片机(8051内核)
拥有T2定时器
12M时钟晶振
P2_0输出控制
舵机角度范围在0~180 高电平范围0.5ms~2.5ms 20ms周期
--------------------------------*/
#include <REGX52.H>
#define T2_PWMout P2_0 //舵机控制端
unsigned int PWMTimes=0;//高电平时间
unsigned char angle=0; //测试角度
void T2_Init();//初始化定时器2
void SetMotoangle(float angle);//设置舵机角度
void Delay100ms(); //@12.000MHz
void main()
{
bit SWdir=0;
T2_Init();//初始化定时器
while(1)//演示程序,舵机左右摆动
{
if(angle>180)SWdir=0;
else if(angle==0)SWdir=1;
SetMotoangle(SWdir?angle++:angle--);
Delay100ms();
}
}
void T2_Init()
{
unsigned int time=65536-20000;
RCAP2L = TL2 = time; //initial timer2 low byte
RCAP2H = TH2 = time >> 8; //initial timer2 high byte
TR2 = 1; //timer2 start running
ET2 = 1; //enable timer2 interrupt
EA = 1; //open global interrupt switch
}
void SetMotoangle(float angle)
{
//防止越界而损伤电机
if(angle > 175) angle = 175;
if(angle <5) angle = 5;
PWMTimes=500+angle*2000.0/180;//计算出高电平时间
}
/* Timer2 interrupt routine */
void tm2_isr() interrupt 5 using 1
{
static bit SW=0;
unsigned int T2count;
TF2 = 0;//标志位清零
SW=~SW;//状态取反
T2_PWMout=SW;//更新输出
if(SW)//低电平时间
{
T2count=0xB1E0+PWMTimes;//0xB1E0即为20ms中断用时
RCAP2L=T2count;
RCAP2H=T2count>>8;
}
else//高电平时间
{
T2count=0-PWMTimes;
RCAP2L=T2count;
RCAP2H=T2count>>8;
}
}
void Delay100ms() //@12.000MHz
{
unsigned char i, j;
i = 195;
j = 138;
do
{
while (--j);
}
while (--i);
}
上一篇:51单片机100例实例之02例
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 蓝牙信道探测技术原理与开发套件实践
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析




