找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3625|回复: 0
收起左侧

为什么89c52单片机不能用串口控制Pwm方波的占空比?

[复制链接]
ID:67093 发表于 2014-10-8 14:00 | 显示全部楼层 |阅读模式
各位大能:

我想编写一个89c52下控制舵机运行的c程序,实现从串口逐次控制pwm方波占空比的功能。比如,从串口向单片机发送一次ff010aff后,方波的宽度就增大一点;发送多次ff010aff后,方波的宽度就可以增大到最多2毫秒。如果发送ff010bff,方波宽度就应该减小,发送多次ff010bff后,方波的宽度就可以减小到最少0.5毫秒。
我在网上找到了一个程序,把它修改了一下后用proteus仿真,但我发现并不能象我想的那样逐次控制pwm方波:从串口输出了命令ff010aff后,方波的宽度一下就变到2毫秒了,从串口输出了命令ff010bff后,方波的宽度一下就变到0.5毫秒了。
我想请教各位大能,为什么我的程序不能象一些51的按键控制程序那样逐次地控制pwm方波的宽度?如何修改才能达到目的呢?请各位不吝赐教。
下面是我的程序:附件里是我的proteus仿真文件。

#include<reg52.h>
#include<math.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar Buffer =0;      //从串口接收的数据
uint i=0,j,URTAReceivedCount=0,n=1;
uchar flag=0;
uchar data Tempdatatable[4],CommandDatatable[4];//数据包
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计数 (实际是460.8,取整得461)
uint code ms2_5Con=2304; //2.5ms计数

/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
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];
      //构建数据包
      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标志统计位
   }
    SBUF = *p;  //发送
   while(!TI)  //如果发送完毕,硬件会置位TI,等待发送完毕
   {
      _nop_();
     }
    p++;
   
    TI = 0;
    if(Send_Count == 2)  //当统计到两次出现0XFF,则认为一个数据包发送完毕,跳出循环
   {
       TI = 0;
         break;
    }  
   }
}
/********************************************************************
* 名称 : Com_Int()
* 功能 : 串口中断子函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Int(void) interrupt 4
{
uchar temp;
ES=0; //关串口中断
    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]);  //发送组成的数据包回去
  }
   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;    //设置波特率 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开关打开                                   
}

/********************************************************************
* 功能 : 舵机PWM中断, //舵机控制函数 周期为20ms 一个循环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])      //根据键值不同,执行不同的内容
           {
            case 0X01:    //类型位0X01,表明是舵机数据包,进入舵机case  
           switch(CommandDatatable[2]) {
              case 0X0A:
         SteeringGearUp(0);
                   break;
              case 0X0B:
          SteeringGearDown(0);
          break;
            }
            break;
        default :  TR0=0;TR2=0;
               break;
       }
     }
   }
}
drivertest01截图00.png

driverictest01.rar

26.89 KB, 下载次数: 397, 下载积分: 黑币 -5

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表