一个PIC16F877A单片机有1个16位守时器TIMER1,咱们用来控制8个舵机(即次序脉冲输出),这样一个单片机就能够操控8个舵机。用8个IO口来操控舵机,舵机操控的信号周期为20mS,而正脉冲最大只要2.5mS,这样有17.5mS是空的。能够选用这种办法:在RD0口输出一个0.5~2.5mS的脉冲,操控一号舵机。完成后,用端口RD1口输出别的一个脉冲,操控2号舵机,就这样下去…..在一号舵机需求第二个脉冲之前,能够输出 20/2.5=8个脉冲,能够用来操控8个舵机,当然,需求用8个IO口。可是一般来说不可能正好有8个2.5mS的脉冲来填满20mS,这样就需求对输出脉冲的总宽度进行累加补偿,然后再用低电平填满20mS中剩余的时刻。一个周期让timer1作业8~9次,前8次每次依据不同舵机的脉宽要求进行守时,每次都对不同的IO口输出脉冲.第九个守时是用来填满20mS的剩余时刻的. 每个口在输完脉冲后,置0 ,然后单片机就不必管他,能够进行下一个IO口的脉冲输出了. 这样一个单片机次序对8个IO口进行脉冲输出. 尽管每个舵机的脉冲时刻有一点推迟,可是不超越20mS,这关于舵机这种低速运转器材来说是彻底感觉不出来的。仿真如下图:
下面就用这种办法进行编程。
#include
unsigned char servo_angle_H[8];
unsigned char servo_angle_L[8];
unsigned char compensate_TL;
unsigned char compensate_TH;
unsigned char p;
void set_servo (unsigned char angle0,unsigned char angle1,
unsigned char angle2,unsigned char angle3,
unsigned char angle4,unsigned char angle5,
unsigned char angle6,unsigned char angle7)
{
unsigned int temp,temp0,value[8];
unsigned char i;
for(i=0;i<8;i++){
servo_angle_H[i]=64468/256;
servo_angle_L[i]=64468%256;
}
compensate_TL=50268%256;
compensate_TH=50268/256;
temp = angle0+angle1+angle2+angle3+angle4+angle5+angle6+angle7;
value[0]=65068-(100*angle0)/9;
value[1]=65068-(100*angle1)/9;
value[2]=65068-(100*angle2)/9;
value[3]=65068-(100*angle3)/9;
value[4]=65068-(100*angle4)/9;
value[5]=65068-(100*angle5)/9;
value[6]=65068-(100*angle6)/9;
value[7]=65068-(100*angle7)/9;
for(i=0;i<8;i++){
servo_angle_H[i]=value[i]/256;
servo_angle_L[i]=value[i]%256;
}
temp0=46068+(100*temp)/9;
compensate_TL=temp0%256;
compensate_TH=temp0/256;
}
//主程序***********************************************************************
void main(void)
{unsigned int a;unsigned int b;
INTCON=0;
GIE=1;//;翻开总中止
PEIE=1;//;翻开外部中止使能位
TMR1IE=1;//;翻开TMR1中止
TRISD=0X00;
PORTD= 0X00;//脉冲波形开始状况
T1CON=0x01;//设置TMR1的操控字
TMR1IF=0;
unsigned char i;
set_servo (13,34,56,87,80,123,156,13);
while(1){;}
}
//中止服务程序*************************************************************
void interrupt timer1(void)
{
TMR1IF=~TMR1IF;
switch(p){
case 0:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0X01;
break;
case 1:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00000010;
break;
case 2:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00000100;
break;
case 3:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00001000;
break;
case 4:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00010000;
break;
case 5:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00100000;
break;
case 6:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B01000000;
break;
case 7:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B10000000;
break;
default:TMR1L=compensate_TL;TMR1H=compensate_TH;PORTD=0B00000000;p=0;
break;
}
p++;
}