关于本程序:
问:定时器1控制着9路pwm 以前听高手帮我讲解 一般8路之内是合适的 因为好像是把舵机的一个周期分成8分来分别控制 超出8路的话 好像周期就有可能改变
答:是的,每路PWM有大约2.5ms是要独立侵占timer时间的,8*2.5刚好20ms,每路舵机范围我只用到0.7~2.0左右,所以9路之间没有干扰。但是个timer之间有干扰。
问:看到个小bug pwm0到pwm8再到pwm0可能不是20ms的一个周期
答:嘿嘿,我把每路的低电平时间合在一起了,然后看它的汇编代码,修正中断中语句用去的时间,上位机算好,用keil的仿真出来是很准的。 在两个timer没有同时中断的情况下精度为0.5us,一旦同时中断,有一路PWM的误差将达到7、8us。
恩 这个中断程序没有结束另外的中断有发生 就会造成后面的中断打失 所以得用性能好的单片机 哈哈
注意本程序在编译的时候要选择pdata模式不然会失败这是工程文件下载已经设置好了模式的: http://www.51hei.com/f/duoji_c.rar
程序源码:
/**************************************************************************
文 件 名:pwm_18out.c
功能描述:利用STC89C52RC做下位机,控制18路舵机PWM
双倍速,机器周期0.5us
日 期:2012-3-19
作 者:cazy peach-ATP
备 注: 18路舵机控制下位机
**************************************************************************/
#define uint unsigned int
#define uchar unsigned char
#include<reg52.h>
sbit pwm9=P1^0;
sbit pwm10=P1^1;
sbit pwm11=P1^2;
sbit pwm12=P1^3;
sbit pwm13=P1^4;
sbit pwm14=P1^5;
sbit pwm15=P1^6;
sbit pwm16=P1^7;
sbit pwm17=P0^7;
sbit pwm0=P2^7;
sbit pwm1=P2^6;
sbit pwm2=P2^5;
sbit pwm3=P2^4;
sbit pwm4=P2^3;
sbit pwm5=P2^2;
sbit pwm6=P2^1;
sbit pwm7=P2^0;
sbit pwm8=P0^6;
//***************************参数申明******************************
//指令格式:两byte为一路PWM,前一个为PWM高电平定时器TH值、后一个为TL的值,由上位机计算所得,共20组。最后两组分别为每9路PWM低电平和。
uint data pwm_val[40]={
0XF4, 0XF0, 0XF7, 0X9B, 0XF6, 0XAE,
0XF4, 0XF9, 0XF8, 0X01, 0XF6, 0X8F,
0XF5, 0X02, 0XF7, 0X2B, 0XF6, 0X9D,
0XF4, 0XF0, 0XF3, 0X1D, 0XF3, 0X16,
0XF4, 0XF9, 0XF2, 0X8B, 0XF3, 0XB0,
0XF5, 0X02, 0XF2, 0XE9, 0XF3, 0X9B,
0XBB, 0X55, 0XD3, 0X04};
uchar zhilin[61];
uchar *point;
uchar data pwm_select=0;
uchar data pwm_scan=0; //timer1使用
uchar data pwm_scan1=0; //timer2使用
uchar data SCI_get=0;
//**************************函数声明****************************
void SCI_INT(void) ;
void timer_INT(void) ;
//***************************主函数*****************************
void main()
{
uchar j;
P0=0X00;
P1=0x00;
P2=0X00;
point=zhilin;
SCI_INT();
timer_INT();
for(j=0;j<61;j++){zhilin[j]=0;}
while(1)
{
for(;;) //指令接收
{
if(RI){RI=0;SCI_get=SBUF;*point++=SCI_get;j++;}else{continue;}
if(SCI_get==0xff){point=zhilin;break;} //0xff指令结束符
}
for(j=0;j<21;j++) //指令处理
{
if(zhilin[j*3]==255){break;} //判断是否为指令结束符
pwm_select=zhilin[j*3];
pwm_val[pwm_select]=zhilin[j*3+1];
pwm_val[pwm_select+1]=zhilin[j*3+2];
}
}
}
//***************************定时器中断**************************
void timer0() interrupt 1 using 1
{
if(pwm_scan==1) //第1路pwm。
{
pwm0=1;
TH0=pwm_val[0];
TL0=pwm_val[1];
}
else if(pwm_scan==2) //第2路pwm。
{
pwm0=0;
pwm1=1;
TH0=pwm_val[2];
TL0=pwm_val[3];
}
else if(pwm_scan==3) //第3路pwm。
{
pwm1=0;
pwm2=1;
TH0=pwm_val[4];
TL0=pwm_val[5];
}
else if(pwm_scan==4) //第4路pwm。
{
pwm2=0;
pwm3=1;
TH0=pwm_val[6];
TL0=pwm_val[7];
}
else if(pwm_scan==5) //第5路pwm。
{
pwm3=0;
pwm4=1;
TH0=pwm_val[8];
TL0=pwm_val[9];
}
else if(pwm_scan==6) //第6路pwm。
{
pwm4=0;
pwm5=1;
TH0=pwm_val[10];
TL0=pwm_val[11];
}
else if(pwm_scan==7) //第7路pwm。
{
pwm5=0;
pwm6=1;
TH0=pwm_val[12];
TL0=pwm_val[13];
}
else if(pwm_scan==8) //第8路pwm。
{
pwm6=0;
pwm7=1;
TH0=pwm_val[14];
TL0=pwm_val[15];
}
else if(pwm_scan==9) //第9路pwm。
{
pwm7=0;
pwm8=1;
TH0=pwm_val[16];
TL0=pwm_val[17];
}
else if(pwm_scan==10) //低电平。
{
pwm8=0;
TH0=pwm_val[36];
TL0=pwm_val[37];
pwm_scan=0;
}
pwm_scan++;
}
void timer1() interrupt 3 using 2
{
if(pwm_scan1==1) //第10路pwm。
{
pwm9=1;
TH1=pwm_val[18];
TL1=pwm_val[19];
}
else if(pwm_scan1==2) //第11路pwm。
{
pwm9=0;
pwm10=1;
TH1=pwm_val[20];
TL1=pwm_val[21];
}
else if(pwm_scan1==3) //第12路pwm。
{
pwm10=0;
pwm11=1;
TH1=pwm_val[22];
TL1=pwm_val[23];
}
else if(pwm_scan1==4) //第13路pwm。
{
pwm11=0;
pwm12=1;
TH1=pwm_val[24];
TL1=pwm_val[25];
}
else if(pwm_scan1==5) //第14路pwm。
{
pwm12=0;
pwm13=1;
TH1=pwm_val[26];
TL1=pwm_val[27];
}
else if(pwm_scan1==6) //第15路pwm。
{
pwm13=0;
pwm14=1;
TH1=pwm_val[28];
TL1=pwm_val[29];
}
else if(pwm_scan1==7) //第16路pwm。
{
pwm14=0;
pwm15=1;
TH1=pwm_val[30];
TL1=pwm_val[31];
}
else if(pwm_scan1==8) //第17路pwm。
{
pwm15=0;
pwm16=1;
TH1=pwm_val[32];
TL1=pwm_val[33];
}
else if(pwm_scan1==9) //第18路pwm。
{
pwm16=0;
pwm17=1;
TH1=pwm_val[34];
TL1=pwm_val[35];
}
else if(pwm_scan1==10) //低电平。
{
pwm17=0;
TH1=pwm_val[38];
TL1=pwm_val[39];
pwm_scan1=0;
}
pwm_scan1++;
}
//********************************函数************************
void timer_INT(void) //timer0、timer1初始化
{
uchar a,b,c;
TMOD|=0X11;
IE|=0X8A; //EA=1;ET0=1;ET1=1;
TH0=256;
TL0=255;
TH1=256;
TL1=255;
TR0=1;
for(c=1;c>0;c--)
{
for(b=38;b>0;b--)
{
for(a=130;a>0;a--);
}
}
TR1=1;
}
void SCI_INT(void) //timer2
{
SCON=0X50;
T2CON=0X30;
TL2=RCAP2L=0XB2; //9600 0XFFB2, 19200 0XFFD9
TH2=RCAP2H=0XFF;
PCON=0X00;
TR2=1;
}