51单片机-PWM调速(直流电机,智能小车的电机调速)
大家好,今天给大家介绍51单片机-PWM调速,下方附有本文涉及的全部资料和源代码的获取方式,可进群免费领取。
一、PWM
PWM即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效的获得所需要的模拟参量。
说白了就是通过控制高低电平的时间,来对输出的波形进行控制。
其中有几个重要的参数
- 频率:频率等于周期频率除以1
- 占空比:高电平在整个周期内所占的时间,即高电平和周期时间的比值
- 精度:占空比变化的步距
二、产生PWM的方法
下方为江科大ppt教程ppt里的图,就是通过定时器定时自增,设置一个比较值,然后通过判断计数器和比较值的大小,输出对应的高低电平。
波形详解,就比如第一个周期内,小于比较值60的部分输出的是低电平,大于比较值60的部分输出高电平。两图的波形等效,PWM波形就这样产生了,控制不同的高低电平存在的时间,然后输出。
使用定时器产生一个恒定的周期
这里没有限制使用什么定时器,当使用多个定时器的时候,一定要注意不同定时器中断和外部中断的优先级,因为如果不同定时器的中断优先级不相同,就有可能一个优先级较高的定时器中断打破了当前定时器产生的中断。使当前中断失效。下方为中断优先级以及使用C语言编程使用到的中断号。
例程序
定时器0产生恒定周期:
#include <REGX52.H> /**
* @brief 定时器0初始化
* @param
* @retval
*/ void Timer0Init() //100us 10ms 11.0592MHZ {
TMOD&=0xF0; //高四位不变 TMOD|=0x01; //设置定时器模式1 以及设置为定时方式 0 TL0 = 0xA4; //设置定时初值 TH0 = 0xFF; //设置定时初值 TF0=0; //定时器0溢出标志位 TR0=1; //定时器0运行控制位 TF0=1; //设置外部中断 ET0=1;
EA=1;
PT0=0;
} //中断函数 /*void Timer0_Rourine() interrupt 1
{
static unsigned int T0count;
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
T0count++;
if(T0count>=1000)
{
T0count=0;
P2_0=~P2_0;
}
}*/
中断服务子程序里设置比较值
和比较值相比较大小,可以自己设置究竟是大于比较值,输出高电平还是低电平,同时小于比较值也同理。
void Timer0_Rourine() interrupt 1 //每隔100us进来一次 {
TL0 = 0xA4; //设置定时初值 TH0 = 0xFF; //设置定时初值 Counter++; if(Counter>=100){Counter=0;} if(Counter<Compare) //小于比较值 输出高电平 {
out1=1; //out代表输出高电平对应的管脚 } else { out=0;
}
三、实验
使用PWM对直流电机调速
通过按键控制直流电机的速度,使速度在数码管上显示,通过PWM调速
主程序
定时器0程序,和上方定时器0,程序相同
#include <REGX52.H> #include "Delay.h" #include "Key.h" #include "Timer0.h" #include "NixieTube.h" sbit motor=P1^0; //电机端口 unsigned char Counter,Compare; //counter 0-100 指的是频率 comapre 指的是占空比 高电平时间 Compare 最大值为100us unsigned char KeyNum,Speed; void main() {
Timer0Init();
Compare=5; while(1)
{
KeyNum=Key(); if(KeyNum==1)
{
Speed++; if(Speed>3){Speed=0;} if(Speed==0){Compare=0;} //compare 指的就是占空比 if(Speed==1){Compare=50;} //5%的占空比 if(Speed==2){Compare=75;} if(Speed==3){Compare=100;}
}
NixieTube(8,Speed);
}
} void Timer0_Rourine() interrupt 1 //每隔100us进来一次 {
TL0 = 0xA4; //设置定时初值 TH0 = 0xFF; //设置定时初值 Counter++; if(Counter>=100){Counter=0;} if(Counter<Compare)
{
motor=1;
} else {
motor=0;
}
}
使用PWM对智能小车的电机调速
直接上源程序啦
在做智能小车的时候肯定大概率会用到,如果你使用PID算法算我没说。
留个小坑,过段时间会把做智能小车遇到问题如何解决的文章分享给大家。
集成了红外循迹、红外避障、红外遥控功能
这个模块可以直接使用
/********************小车PWM输出****************/ /**
* @brief 小车PWM输出 装载PWM输出,如果设置全局变量pwm_left,pwm_right分别配置左右输出高电平时间
* @param 无
* @retval 无
*/ void LoadPWM(void) { if(pwm_left > PWM_HIGH_MAX) pwm_left = PWM_HIGH_MAX; //如果左输出写入大于最大占空比数据,则强制为最大占空比。 if(pwm_left < PWM_HIGH_MIN) pwm_left = PWM_HIGH_MIN; //如果左输出写入小于最小占空比数据,则强制为最小占空比。 if(pwm_right > PWM_HIGH_MAX) pwm_right = PWM_HIGH_MAX; //如果右输出写入大于最大占空比数据,则强制为最大占空比。 if(pwm_right < PWM_HIGH_MIN) pwm_right = PWM_HIGH_MIN; //如果右输出写入小于最小占空比数据,则强制为最小占空比。 if(pwm_val_left<=pwm_left) Left_moto_pwm = 1; //装载左PWM输出高电平时间 else Left_moto_pwm = 0; //装载左PWM输出低电平时间 if(pwm_val_left>=PWM_DUTY) pwm_val_left = 0; //如果左对比值大于等于最大占空比数据,则为零 if(pwm_val_right<=pwm_right) Right_moto_pwm = 1; //装载右PWM输出高电平时间 else Right_moto_pwm = 0; //装载右PWM输出低电平时间 if(pwm_val_right>=PWM_DUTY) pwm_val_right = 0; //如果右对比值大于等于最大占空比数据,则为零 } void Timer1_Routine() interrupt 3 {
pwm_val_left++;
pwm_val_right++;
LoadPWM();//装载PWM输出 }
总结
说白了,PWM就是设置一个恒定的周期内,通过设置计时数和设置的比较值的大小,是在计时数比比较值小置高低电平,则要依据自己的需求来进行设置。
这个PWM起初还不知道是啥,看了江科大第一遍视频没懂,第二遍懂了一点点,后面查看了好几个资料,摸着摸着不知道怎么就明白了个大概。
初始接触是应为江科大的视频里,一步一步跟下来
再接触是自己制作的智能小车的速度一直慢不下来,所以使用PWM对小车的速度进行控制
- 赞