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對小車的速度進行控制
- 贊