风铃 发表于 2013-1-20 19:20:56

STC单片机驱动舵机,舵机左右循环乱动。懂的大神请进

大神们,小弟我用STC12C单片机自带的PCA/PWM功能模块驱动一路舵机(型号MG945),结果出现了实在想不通的问题,研究了一天都没个头绪,无奈之下来请教坛子里的兄弟们。
问题主要就是:先让舵机转一个角度,然后延时一会,再让舵机转另外一个角度,顺序执行,理想的结果应该就是转两次就完了。因为我并没有让他在while(1)循环里,可是现象却是舵机来回转动,执行N多次,停不下来。断开舵机,直接接上示波器观察,却发现是好的, 直接执行一遍,最后输出的是稳定不变的PWM波。我就糊涂了。
源代码如下:劳烦大神们指点一下。谢谢了。
/*利用单片机的PWM功能,产生PWM波,占空比、周期和相位可调*/
#include"PWM.h"

#define Mode2        1             //输入时钟源模式:由定时器0的溢出率决定
                                             //Fpwm=11059200/256/(65536-TH0*256-TL0)
#define Mode1        0             //输入时钟源模式:Fpwm恒定为sysclk/2/256=21.6kHz
unsigned char an_temp;//角度调整中间变量

/******************************************************************************
**函数:PWM_Init
**功能:PWM波输出前的初始化
**输入        :无
**输出        : 无
**返回        : 无
*******************************************************************************/
void PWM_Init(void)
{
    CCON=0;            //初始化PCA 控制寄存器
        CL=0;                             //16位计数器低位,控制占空比 ,用于保存PCA的装载值
        CH=0;                             //16位计数器高位,控制占空比

#if Mode1
        CMOD=0x02;         //设置PCA时钟源是Sysclk/2
#endif

#if Mode2

        AUXR|=0x80;         //使定时器工作于1T模式,每一个系统周期计一个数
        TMOD|=0x01;         //定时器0工作于方式2(16位)
        TL0=174;                          //使输出频率为50Hz的计数初值,控制舵机
        TH0=252;
        TR0=1;                                  //开定时器
        ET0=1;                                  //开定时器中断
        EA=1;                                  //开总中断
        CMOD=0x05;                          //设置PCA时钟源是定时器的溢出频率
#endif
    PCAPWM0=0x00;      //清零PWM模式下的第九位
//        ECPA_LVD=1;
        CCAPM1=0x42;                         //使工作于PWM模式
        CCAPM0=0x42;                         //使工作于PWM模式
        CR=1;                        //PCA定时器开始计时       
}

/******************************************************************************
**函数:PWM0_adjust
**功能:PWM0输出PWM波的占空比调整,angle_0为0~180,舵机控制的比例是2.5%~12%
          所以改变angle_0的值可以改变占空比3%~12%
**输入        :angle_0
**输出        : 无
**返回        : 无
*******************************************************************************/
void PWM0_adjust(unsigned char angle_0)
{
    an_temp=(unsigned char)(angle_0*0.13333);
        CCAP0H=0xf8-an_temp;             //高电平时间
        CCAP0L=0x08+an_temp;               //低电平时间
}

/******************************************************************************
**函数:PWM1_adjust
**功能:PWM1输出PWM波的占空比调整,angle_1为0~180,舵机控制的比例是2.5%~12%
          所以改变angle_1的值可以改变占空比3%~12%
**输入        :angle_1
**输出        : 无
**返回        : 无
*******************************************************************************/
void PWM1_adjust(unsigned char angle_1)
{
    an_temp=(unsigned char)(angle_1/7.5);
        CCAP1H=0xf8-an_temp;             //高电平时间
        CCAP1L=0x08-an_temp;               //低电平时间
}

/******************************************************************************
**函数:PWM2_adjust
**功能:PWM2输出PWM波的占空比调整,angle_2为0~180,舵机控制的比例是2.5%~12%
          所以改变angle_0的值可以改变占空比3%~12%
**输入        :angle_2
**输出        : 无
**返回        : 无
*******************************************************************************/
void PWM2_adjust(unsigned char angle_2)
{
    an_temp=(unsigned char)(angle_2/7.5);
        CCAP2H=0xf8-an_temp;             //高电平时间
        CCAP2L=0x08+an_temp;               //低电平时间
        CCAPM2=0x42;                         //使工作于PWM模式
}

/*****************************************************************************
**函数:定时器0中断服务函数
**功能:重新赋初值,改变初值,可以改变输出PWM波的频率
**输入        :无
**输出        : 无
**返回        : 无
******************************************************************************/
void timer0_ISR() interrupt 1 using 1
{
    TL0=174;       //重新赋初值
        TH0=252;
    TF0=0;
}


//主程序在这里
void main(void)
{       

                  // 初始化IO口                                                          
        P1M0 = 0x00;                                            // P1全部为准双向口(传统8051模式)           
        P1M1 = 0x00;
        P2M0 = 0x00;                                                //不设置时默认
        P2M1 = 0x00;   
        P3M0 = 0x00;                                                // P3全部为准双向口
        P3M1 = 0x00;

          PWM_Init();
       
          PWM1_adjust(10);             //先转动10度
          delay_ms(2000);               
          PWM1_adjust(40);         //后转动40度
          delay_ms(1000);
          while(1);
}

amfan 发表于 2013-1-20 19:57:18

转动的角度对吗?
我用3.3v的stc单片机,要加上拉才行

ahuang227 发表于 2013-1-20 20:58:32

频率多少呢?

风铃 发表于 2013-1-20 21:47:31

amfan 发表于 2013-1-20 19:57 static/image/common/back.gif
转动的角度对吗?
我用3.3v的stc单片机,要加上拉才行

我加上了10k的上拉电阻的。

风铃 发表于 2013-1-20 21:49:35

ahuang227 发表于 2013-1-20 20:58 static/image/common/back.gif
频率多少呢?

频率是50Hz,可以驱动电机,角度是对的,就是左右以我设定的角度转来转去,比如说我设30度和60度,他就是左转30度,右转60度,如此循环(我程序里没循环),不知何故

jlhgold 发表于 2013-1-21 08:12:36

你是不是需要停止使能pwm中断啊?

marshallemon 发表于 2013-1-21 08:19:06

光while不行要关掉Pca

ahuang227 发表于 2013-1-21 08:43:58

风铃 发表于 2013-1-20 21:47 static/image/common/back.gif
我加上了10k的上拉电阻的。

PWM不用接上拉的。

ahuang227 发表于 2013-1-21 08:44:44

风铃 发表于 2013-1-20 21:49 static/image/common/back.gif
频率是50Hz,可以驱动电机,角度是对的,就是左右以我设定的角度转来转去,比如说我设30度和60度,他就是 ...

上两个示波器的图看看。

我用timer的中断做的是好用的。

NJ8888 发表于 2013-1-21 08:46:49

是应当用示波器看到位时脉宽是否在抖动

风铃 发表于 2013-1-28 09:33:25

NJ8888 发表于 2013-1-21 08:46 static/image/common/back.gif
是应当用示波器看到位时脉宽是否在抖动

谢谢您的指导与回答。真的很不好意思,因为回家了,今天出来网吧上的。。。所以晚回复你了。回家前我解决了这个问题了。原因是对舵机的供电没有与单片机隔离开来,导致舵机运动队单片机产生严重的干扰,甚至让单片机复位。分开供电,或者多加上几个电容和电感,问题就没了。

风铃 发表于 2013-1-28 09:34:07

ahuang227 发表于 2013-1-21 08:44 static/image/common/back.gif
上两个示波器的图看看。

我用timer的中断做的是好用的。

谢谢您的指导与回答。真的很不好意思,因为回家了,今天出来网吧上的。。。所以晚回复你了。回家前我解决了这个问题了。原因是对舵机的供电没有与单片机隔离开来,导致舵机运动队单片机产生严重的干扰,甚至让单片机复位。分开供电,或者多加上几个电容和电感,问题就没了。

风铃 发表于 2013-1-28 09:35:03

jlhgold 发表于 2013-1-21 08:12 static/image/common/back.gif
你是不是需要停止使能pwm中断啊?

我没有加上PWM中断哦。问题解决了,原因是供电问题。谢谢您!

风铃 发表于 2013-1-28 09:35:55

ahuang227 发表于 2013-1-21 08:43 static/image/common/back.gif
PWM不用接上拉的。

恩恩,这个确实,我当时看了单片机的指导手册才加的,后来发现不对,果断不能加上拉电阻啊,消耗我电流。

风铃 发表于 2013-1-28 09:37:26

marshallemon 发表于 2013-1-21 08:19 static/image/common/back.gif
光while不行要关掉Pca

嗯嗯,不过,开始时直接在初始化里开了。完成动作后就关掉PCA

loveye21 发表于 2013-1-28 12:48:22

看看是不是电源问题。我之前遇到过这种情况.

风铃 发表于 2013-1-28 14:58:58

loveye21 发表于 2013-1-28 12:48 static/image/common/back.gif
看看是不是电源问题。我之前遇到过这种情况.

恩恩,很对,就是电源问题,没有足够重视舵机的噪声啊!

wwt3100_凸 发表于 2013-1-30 23:06:21

除了用独立供电外,我还加施密特发生器

风铃 发表于 2013-2-21 15:09:05

wwt3100_凸 发表于 2013-1-30 23:06 static/image/common/back.gif
除了用独立供电外,我还加施密特发生器

请教一下, 为什么还要加施密特发生器呢?

fmmdptt163 发表于 2013-7-19 20:40:37

单片机复位了,供电不足
页: [1]
查看完整版本: STC单片机驱动舵机,舵机左右循环乱动。懂的大神请进