1. 程式人生 > >使用51微控制器輸出PWM控制舵機

使用51微控制器輸出PWM控制舵機

SCU 的電子資訊學院的某個社團會每年舉辦船模大賽。


因為去年的船模比賽時候懶,所以就買了成品的遙控器(天地飛6)來參賽,控制自己製作的遙控船上面的電調和舵機。最近有心情想在今年的船模比賽中自己製作遙控器,先從第一步開始吧:使用微控制器來控制舵機(控制電調的原理類似)。

0x01.什麼是舵機?

        其實舵機就是一種伺服電機,根據要求旋轉一定的角度,在我看來,知道這些就夠了~~

0x02.舵機有什麼用?

        就拿模型來說吧,船要轉彎的話,可以採用的一種方式就是改變船後面舵片的角度來改變兩側對水的阻力,以此來讓船轉向,這個也是舵機一詞的由來。

0x03.怎麼控制?

        PWM波,這是什麼東西呢?其實就是一種方波,其頻率為50Hz,週期就是20ms,在每個週期裡面,高電平的佔空比在0.5ms到2.5ms之間。而0.5ms代表的是0度,2.5ms代表的是180度。其他的度數可以直接按照比例換算過去*(這個有點想ARDUINO裡面的map函式的意思)

0x04.如何實現PWM?

        實現脈衝寬度調製波有很多種方法,很多微控制器已經有“原生支援”的pwm輸出引腳,用來輸出pwm波形。

        我採用比較土的一種方法,如下圖:

就用這玩意輸出了,他是STC公司生產的89C52RC型號的微控制器,核心是51微控制器,運用其中的定時器中斷方式輸出pwm波。

0x05.實現效果

       是用微控制器的P2^7引腳輸出PWM波形,使用P2^4,P2^5引腳操作獨立按鍵來控制舵機的角度

使用KEIL 4平臺,程式碼如下:

主函式:

// GYZ
// 1路PWM波形輸出,可以控制舵機和電調

#include<reg52.h>

//引腳位定義
sbit key1 = P2^5;
sbit key2 = P2^4;  //獨立按鍵引腳
sbit pwm1 = P2^7;

//全域性變數定義 
unsigned int target =6,percent = 0;

// 標頭檔案包含
#include<Timer.h>
#include<interrupt.h>	
#include<key.h>

//函式宣告
void Timer0Initial();
void initial_Timer();
void delay(unsigned int x);
void keyscan();


void main()
{
	initial();
	while(1)
	{
		keyscan();
	}
}


獨立按鍵掃描

key.h

void keyscan()
{
	if(key1 == 0)
	{
	delay(3);
	if(key1 == 0)
	{
		if(target >= 7)
		{
			target -= 1;
		}
		while(key1 == 0)
		{P1 = 0x00;}
	}
	P1 = 0xFF;
	}

	if(key2 == 0)
	{
		delay(3);
		if(key2 == 0)
		{
			if(target <= 26)
			{
				target += 1;
			}
			while(key2 == 0)
			{P1 = 0x00;}
		}
		P1 = 0xFF;
	}
}//按鍵檢測程式

void initial()
{
	key1 = 1;
	key2 = 1;
	P1 = 0xff;
	initial_Timer();
}

定時器程式

Timer.h

//Timer Configuration
//使用12Mhz晶振
//理論上,12Mhz晶振12分頻之後
//應該是100次計數時間是100us
//通過示波器實測
//選用65次計數產生一次中斷

void Timer0Initial()
{
	TH0 = (65536-65)/256;
	TL0 = (65536-65)%256;
} //該初值使每0.1ms產生一次中斷

void initial_Timer()
{
	EA = 1;		   //開啟總中斷
	ET0 = 1;	   //允許T0中斷
	TMOD = 0x01;	//定時器模式,T0使用工作方式1
	Timer0Initial();	  //裝初值,0.1ms產生一次中斷
	TR0 = 1;			  //開啟T0定時器
}

void delay(unsigned int x)
{
	unsigned int i,j;
	for(i = 0;i< x; ++i)
		for(j = 120; j >0 ; --j)
			;
}


最後,中斷的程式

interrupt.h

void Timer0() interrupt 1 using 0
{
	percent += 1;
	if(percent == 200)
	{
		percent = 0;
		pwm1 = 1;//拉高電平的引腳,來維持50hz的頻率
	}
	if(percent == target)
	{
		pwm1 = 0;
	}
	Timer0Initial();

}