|
各位大能:
我想編寫一個89c52下控制舵機運行的c程序,實現(xiàn)從串口逐次控制pwm方波占空比的功能。比如,從串口向單片機發(fā)送一次ff010aff后,方波的寬度就增大一點;發(fā)送多次ff010aff后,方波的寬度就可以增大到最多2毫秒。如果發(fā)送ff010bff,方波寬度就應(yīng)該減小,發(fā)送多次ff010bff后,方波的寬度就可以減小到最少0.5毫秒。
我在網(wǎng)上找到了一個程序,把它修改了一下后用proteus仿真,但我發(fā)現(xiàn)并不能象我想的那樣逐次控制pwm方波:從串口輸出了命令ff010aff后,方波的寬度一下就變到2毫秒了,從串口輸出了命令ff010bff后,方波的寬度一下就變到0.5毫秒了。
我想請教各位大能,為什么我的程序不能象一些51的按鍵控制程序那樣逐次地控制pwm方波的寬度?如何修改才能達(dá)到目的呢?請各位不吝賜教。
下面是我的程序:附件里是我的proteus仿真文件。
#include<reg52.h>
#include<math.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar Buffer =0; //從串口接收的數(shù)據(jù)
uint i=0,j,URTAReceivedCount=0,n=1;
uchar flag=0;
uchar data Tempdatatable[4],CommandDatatable[4];//數(shù)據(jù)包
sbit servo0=P0^0;
uchar serVal[2];
uint pwm[]={1382,1382,1382,1382,1382,1382,1382,1382}; //初始90度,(實際是1382.4,取整得1382)
uchar pwm_flag=0;
uint code ms0_5Con=461; //0.5ms計數(shù) (實際是460.8,取整得461)
uint code ms2_5Con=2304; //2.5ms計數(shù)
/********************************************************************
* 名稱 : Delay_1ms()
* 功能 : 延時子程序,延時時間為 1ms * x
* 輸入 : x (延時一毫秒的個數(shù))
* 輸出 : 無
***********************************************************************/
void Delay_1ms(uint i)//1ms延時
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
/********************************************************************
* 名稱 : Send_Data()
* 功能 : 向上位機傳送字符
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Send_Data(uchar data type,uchar data cmd)
{
uchar data Buffer[4];
//構(gòu)建數(shù)據(jù)包
uchar *p;
uint Send_Count=0;
p = Buffer;
Buffer[0]=0XFF;
Buffer[1]=type;
Buffer[2]=cmd;
Buffer[3]=0XFF;
while(1){
if(*p==0XFF){
Send_Count++; //0XFF標(biāo)志統(tǒng)計位
}
SBUF = *p; //發(fā)送
while(!TI) //如果發(fā)送完畢,硬件會置位TI,等待發(fā)送完畢
{
_nop_();
}
p++;
TI = 0;
if(Send_Count == 2) //當(dāng)統(tǒng)計到兩次出現(xiàn)0XFF,則認(rèn)為一個數(shù)據(jù)包發(fā)送完畢,跳出循環(huán)
{
TI = 0;
break;
}
}
}
/********************************************************************
* 名稱 : Com_Int()
* 功能 : 串口中斷子函數(shù)
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Com_Int(void) interrupt 4
{
uchar temp;
ES=0; //關(guān)串口中斷
RI=0; //軟件清除接收中斷
temp=SBUF;
if(temp==0XFF && URTAReceivedCount<2)
{
Tempdatatable[0]==0XFF; //包頭
URTAReceivedCount++;
}
else
{
Tempdatatable[n]=temp;
n++;
}
if(URTAReceivedCount==2)//包尾
{
Tempdatatable[0]=0XFF;
Tempdatatable[3]=0XFF;
n=1;
URTAReceivedCount=0; //組包完畢
temp="";
//Send_Data(Tempdatatable[1],Tempdatatable[2]); //發(fā)送組成的數(shù)據(jù)包回去
}
CommandDatatable[0]=Tempdatatable[0];
CommandDatatable[1]=Tempdatatable[1];
CommandDatatable[2]=Tempdatatable[2];
CommandDatatable[3]=Tempdatatable[3];
ES=1;//開串口中斷
}
/********************************************************************
* 名稱 : Com_Init()
* 功能 : 串口初始化,晶振11.0592,波特率9600,使能了串口中斷
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Com_Init(void)
{
TMOD |= 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd; //設(shè)置波特率 9600
TL1 = 0xFd;
TR1 = 1; //啟動定時器1
ES = 1; //開串口中斷
EA = 1; //開總中斷
IT0=0;
EX0=1;
}
/********************************************************************
* 功能 : 舵機PWM中斷初始化
***********************************************************************/
void Timer0Init() {
//0度=0.5ms, 45度=1ms, 90度=1.5ms, 135度=2ms, 180度=2.5ms
//2.5 ms初始值 F700, (12n/11059200=2.5/1000, n=2304, X=65536-2304=63232 > F700)
TMOD |= 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響
TH0=-ms2_5Con>>8; //給定初值,17ms中斷
TL0=-ms2_5Con;
EA=1; //總中斷打開
ET0=1; //定時器0中斷打開
TR0=1; //定時器0開關(guān)打開
}
/********************************************************************
* 功能 : 舵機PWM中斷, //舵機控制函數(shù) 周期為20ms 一個循環(huán)20MS = 8*2.5ms
***********************************************************************/
void SteeringGear() interrupt 1 {
switch(pwm_flag)
{
case 1:
servo0=1;
TH0=-pwm[0]>>8;
TL0=-pwm[0];
break;
case 2:
servo0=0;
TH0=-(ms2_5Con-pwm[0])>>8;
TL0=-(ms2_5Con-pwm[0]);
break;
//...
default:
TH0=0xff;
TL0=0x80;
pwm_flag=0;
}
pwm_flag++;
}
void SteeringGearUp(uchar i) {
if(pwm>ms0_5Con)
pwm=pwm-10;
}
void SteeringGearDown(uchar i) {
if(pwm<ms2_5Con)
pwm=pwm+10;
}
void main()
{
Delay_1ms(200);
Com_Init();//串口初始化
Timer0Init();//舵機初始化
while(1)
{
if(CommandDatatable[0]==0XFF && CommandDatatable[3]==0XFF){
switch (CommandDatatable[1]) //根據(jù)鍵值不同,執(zhí)行不同的內(nèi)容
{
case 0X01: //類型位0X01,表明是舵機數(shù)據(jù)包,進(jìn)入舵機case
switch(CommandDatatable[2]) {
case 0X0A:
SteeringGearUp(0);
break;
case 0X0B:
SteeringGearDown(0);
break;
}
break;
default : TR0=0;TR2=0;
break;
}
}
}
}
|
|