這是具體程序
#include "reg51.h"
#define uint8 unsigned char //無符號字符型
#define uint16 unsigned short int
#define uint32 unsigned long
sbit SERVO0=P3^6; //控制舵機的PWM輸出口
sbit SERVO1=P3^5;
sbit kaishi=P1^1;
sbit jieshu=P1^2;
sbit jiare=P3^3;
sbit jianre=P3^4;
uint16 Servo0PwmDuty0=1500; //PWM脈沖寬度 1.5ms脈沖寬度
uint16 Servo0PwmDuty1=1500;
/***********************************************************
* 名 稱: DelayMs(uint16 ms)
* 功 能: 延時ms毫秒
* 入口參數: ms 毫秒
* 出口參數: 無
* 說 明:
/**********************************************************/
void DelayMs(uint16 ms)
{
uint16 i,j;
for(i=0;i<85;i++) //89單片機用85,12系列單片機用800
for(j=0;j<ms;j++);
}
/***********************************************************
* 名 稱:InitTimer0()
* 功 能:時鐘0初始化
* 入口參數:無
* 出口參數:無
* 說 明:12M晶振,12分頻,所以計數器每遞增一個數就是1微秒,完全滿足舵機控制的精度要求
因為定時器是TH0,TL0都要全部計數到0xFF后在計1個數就會產生中斷,所以要想產生
x毫秒的中斷,那么TH0,TL0就應該賦值(0xFFFF-x) 從這個值開始計數產生定時中斷
/**********************************************************/
void InitTimer0(void)
{
TMOD = 0x11; //設置定時器模式
TL0 = 0x00; //設置定時初值
TH0 = 0x00; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0 = 1;
TL1 = 0x00; //設置定時初值
TH1 = 0x00; //設置定時初值
TF1 = 0; //清除TF0標志
TR1 = 1; //定時器0開始計時
ET1 = 1; //開定時器0中斷
}
/***********************************************************
* 名 稱:Timer0Value(uint16 pwm)
* 功 能:給定時器0計數器賦值產生定時中斷
* 入口參數:pwm 控制舵機的PWM脈沖寬度值(范圍:500~2500)
* 出口參數:無
* 說 明:12M晶振,12分頻,所以計數器每遞增一個數就是1微秒,完全滿足舵機控制的精度要求
因為定時器是TH0,TL0都要全部計數到0xFF后在計1個數就會產生中斷,所以要想產生
pwm毫秒的中斷,那么TH0,TL0就應該賦值(0xFFFF-pwm) 從這個值開始計數產生定時中斷
/**********************************************************/
void Timer0Value(uint16 pwm)
{
uint16 value;
value=0xffff-pwm;
TR0 = 0;
TL0=value; //16位數據給8位數據賦值默認將16位數據的低八位直接賦給八位數據
TH0=value>>8; //將16位數據右移8位,也就是將高8位移到低八位,再賦值給8位數據
TR0 = 1;
}
void Timer1Value(uint16 pwm)
{
uint16 value;
value=0xffff-pwm;
TR1 = 0;
TL1=value; //16位數據給8位數據賦值默認將16位數據的低八位直接賦給八位數據
TH1=value>>8; //將16位數據右移8位,也就是將高8位移到低八位,再賦值給8位數據
TR1 = 1;
}
/***********************************************************
* 名 稱: main()
* 功 能: 入口函數
* 入口參數: 無
* 出口參數: 無
* 說 明:
/**********************************************************/
void main(void)
{
InitTimer0(); //定時器0初始化
EA = 1; //開總中斷
while(1) //大循環
{
if(kaishi==0)
{
Servo0PwmDuty0 = 1500;Servo0PwmDuty1 = 1500;
DelayMs(1000);
}
if(jieshu==0)
{
Servo0PwmDuty0 = 500;Servo0PwmDuty1 = 500;
DelayMs(1000);
}
if(jiare==0)
{
Servo0PwmDuty0=Servo0PwmDuty0+100;Servo0PwmDuty1=Servo0PwmDuty1-100;
DelayMs(1000);
if(Servo0PwmDuty0>=2500){Servo0PwmDuty0=2500;}
if(Servo0PwmDuty1<=500){Servo0PwmDuty1=500;}
}
if(jianre==0)
{
Servo0PwmDuty0=Servo0PwmDuty0-100;Servo0PwmDuty1=Servo0PwmDuty1+100;
DelayMs(1000);
if(Servo0PwmDuty1>=2500){Servo0PwmDuty1=2500;}
if(Servo0PwmDuty0<=500){Servo0PwmDuty0=500;}
}
}
}
void Timer_0(void) interrupt 1 using 1
{
static uint16 i = 1; //靜態變量:每次調用函數時保持上一次所賦的值,
//跟全局變量類似,不同是它只能用于此函數內部
switch(i)
{
case 1:
SERVO0 = 1; //PWM控制腳高電平
//給定時器0賦值,計數Pwm0Duty個脈沖后產生中斷,下次中斷會進入下一個case語句
Timer0Value(Servo0PwmDuty0);
break;
case 2:
SERVO0 = 0; //PWM控制腳低電平
//高脈沖結束后剩下的時間(20000-Pwm0Duty)全是低電平了,Pwm0Duty + (20000-Pwm0Duty) = 20000個脈沖正好為一個周期20毫秒
Timer0Value(20000-Servo0PwmDuty0);
i = 0;
break;
}
i++;
}
void Timer_1(void) interrupt 3 using 1
{
static uint16 j = 1; //靜態變量:每次調用函數時保持上一次所賦的值,
//跟全局變量類似,不同是它只能用于此函數內部
switch(j)
{
case 1:
SERVO1 = 1; //PWM控制腳高電平
//給定時器0賦值,計數Pwm0Duty個脈沖后產生中斷,下次中斷會進入下一個case語句
Timer1Value(Servo0PwmDuty1);
break;
case 2:
SERVO1 = 0; //PWM控制腳低電平
//高脈沖結束后剩下的時間(20000-Pwm0Duty)全是低電平了,Pwm0Duty + (20000-Pwm0Duty) = 20000個脈沖正好為一個周期20毫秒
Timer1Value(20000-Servo0PwmDuty1);
j = 0;
break;
}
j++;
} |