我想用AVR的一个定时器中断来控制舵机的左右45度转动,请问中断程序怎么写呢

我想用AVR的一个定时器中断来控制舵机的左右45度转动,请问中断程序怎么写呢,第1张

先要知道舵机控制的原理,控制波形PWM的占空比决定了舵机的控制角度,你需要每个角度它所对应的占空比是多少,从1个角度转到另1个角度是占空比慢慢转变的过程,而波形的周期是不变的。接下来就是单片机控制PWM波形占空比的实现,这个比较简单,可以用定时器也可以不用,具体程序思路就不说了,每个人思路都不一样,能保证输出波形正确就OK了

#include "reg52h"

unsigned char count; //05ms次数标识

sbit pwm =P1^7 ; //PWM信号输出

sbit jia =P3^6; //角度增加按键检测IO口

sbit jan =P3^7; //角度减少按键检测IO口

unsigned char jd; //角度标识

unsigned char flag;

sbit dula=P2^6;

sbit wela=P2^7;

unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void delay(unsigned char i)//延时

{

unsigned char j,k;

for(j=i;j>0;j--)

for(k=125;k>0;k--);

}

void Time0_Init() //定时器初始化

{

TMOD = 0x01; //定时器0工作在方式1

IE = 0x82;

TH0 = 0xfe;

TL0 = 0x33; //110592MZ晶振,05ms

TR0=1; //定时器开始

}

void Time0_Int() interrupt 1 //中断程序

{

TH0 = 0xfe; //重新赋值

TL0 = 0x33;

if(flag!=29||jd!=1) //这个判断是为了在0度时让信号线只输出30个周期的PWM信号,然后就让信号线为低电平

{

if(count<jd) //判断05ms次数是否小于角度标识

pwm=1; //确实小于,PWM输出高电平

else

pwm=0;

}

count=(count+1); //05ms次数加1

if(count==39) //次数始终保持为40 即保持周期为20ms

{

count=0;

if(jd==1)

if(flag!=29)

flag=flag+1; //如果30个周期已经到了,则保持这个flag为29,使在前面的判断中不在输出PWM信号

}

}

void keyscan() //按键扫描

{

if(jia==0) //角度增加按键是否按下

{

delay(10); //按下延时,消抖

if(jia==0) //确实按下

{ flag=0; //有键按下就让flag为0,这样当再次要使电机为0度时可以再次输出30个周期的PWM信号

jd++; //角度标识加1

count=0; //按键按下 则20ms周期从新开始

if(jd==6)

jd=5; //已经是180度,则保持

while(jia==0); //等待按键放开

}

}

if(jan==0) //角度减小按键是否按下

{

delay(10);

if(jan==0)

{flag=0; //有键按下就让flag为0,这样当再次要使电机为0度时可以再次输出30个周期的PWM信号

jd--; //角度标识减1

count=0;

if(jd==0)

jd=1; //已经是0度,则保持

while(jan==0);

}

}

}

void display() //数码管显示函数

{

unsigned char bai,shi,ge;

switch(jd) //根据角度标识显示相应的数值

{

case 1: //为1,角度为0,前3个数码管显示000

bai=0;

shi=0;

ge=0;

break;

case 2:

bai=0;

shi=4;

ge=5;

break;

case 3:

bai=0;

shi=9;

ge=0;

break;

case 4:

bai=1;

shi=3;

ge=5;

break;

case 5: //为5,角度为180,前3个数码管显示180

bai=1;

shi=8;

ge=0;

break;

}

dula=0;

P0=table[bai];

dula=1;

dula=0;

wela=0;

P0=0xfe;

wela=1;

wela=0;

delay(5);

P0=table[shi];

dula=1;

dula=0;

P0=0xfd;

wela=1;

wela=0;

delay(5);

P0=table[ge];

dula=1;

dula=0;

P0=0xfb;

wela=1;

wela=0;

delay(5);

}

void main()

{

jd=1;

flag=0;

count=0;

pwm=0;

Time0_Init();

while(1)

{

keyscan(); //按键扫描

display();

}

}

占空比很简单,控制高电平持续时间和低电平持续时间就可以了。

while(1){

SetIOH

Delay(5us),

SetIOL

Delay(5us)

}

就是一个占空比50%,频率为100k的PWM方波了。

以上是伪代码,具体的需要看MG995的实现。

舵机是一种位置伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。其工作原理是:控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为15ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。编程的时候也很简单,你将一根管脚初始化为低电平,然后写一个while循环,在循环中将该脚职位高电平,延时,再拉为低电平,如此不停的循环就是PWM波,你需要控制的是高电平产生的时间,根据高电平的时间来控制舵机的角度的,希望能帮的上你

20ms为舵机周期,一个周期可以同时控制8个舵机,20/25=8

用定时器产生脉冲,两个定时器T0,T1,82,同时可以控制16个舵机,

以下是用按键控制一个舵机的转动,你可以参考以下程序,多设个io口,在switch函数中的 条件语句中加各个io口脉宽,以下程序中的例如:case 0中的if可以多加几个io控制就可以同时控制多个了,程序前面也可以开定时器T0,以下就只开T1。懒得改以下程序,你参考下就明白了,原理明白就好搞,以下程序很基础,很简单明了了。

#include <reg52h>

#define Stop 0 //宏定义,停止

#define Left 1 //宏定义,左转

#define Right 2 //宏定义,右转

sbit ControlPort = P1^1; //舵机信号端口

sbit KeyLeft = P3^2; //左转按键端口

sbit KeyRight = P3^3; //右转按键端口

sbit KeyStop = P1^3; //归位按键端口

unsigned char TimeOutCounter = 0,LeftOrRight = 0; //TimeOutCounter:定时器溢出计数 LeftOrRight:舵机左右旋转标志

void InitialTimer ( )

{

TMOD=0x10; //定时/计数器1工作于方式1

TH1 = ( 65535 -87 ) / 256; //01ms

TL1 = ( 65535 - 87 ) % 256;

EA=1; //开总中断

ET1=1; //允许定时/计数器1 中断

TR1=1; //启动定时/计数器1 中断

}

ControlLeftOrRight ( ) //控制舵机函数

{

if( KeyStop == 0 )

{

while ( !KeyStop ); //使标志等于Stop(0),在中断函数中将用到

LeftOrRight = Stop;

}

if( KeyLeft == 0 )

{

while ( !KeyLeft ); //使标志等于Left(1),在中断函数中将用到

LeftOrRight = Left;

}

if( KeyRight == 0 )

{

while ( !KeyRight ); //使标志等于Right(2),在中断函数中将用到

LeftOrRight = Right;

}

}

main ( ) //主函数

{

InitialTimer();

for(;;)

{

ControlLeftOrRight();

}

}

void Timer1 ( void ) interrupt 3 //定时器中断函数

{

TH1 = ( 65535 - 87 ) / 256;

TL1 = ( 65535 - 87 ) % 256;

TimeOutCounter ++;

switch ( LeftOrRight )

{

case 0 : //为0时,舵机归位,脉宽15ms

{

if( TimeOutCounter <= 15 )

{

ControlPort = 1;

}

else

{

ControlPort = 0;

}

break;

}

case 1 : //为1时,舵机左转,脉宽1ms(理论值),实际可以调试得出

{

if( TimeOutCounter <= 10)

{

ControlPort = 1;

}

else

{

ControlPort = 0;

}

break;

}

case 2 : //为2时,舵机右转,脉宽2ms(理论值),实际可以调试得出

{

if( TimeOutCounter <=22 )

{

ControlPort = 1;

}

else

{

ControlPort = 0;

}

break;

}

default : break;

}

if( TimeOutCounter == 200 ) //周期20ms(理论值),比较可靠,最好不要修改

{

TimeOutCounter = 0;

}

}

以上就是关于我想用AVR的一个定时器中断来控制舵机的左右45度转动,请问中断程序怎么写呢全部的内容,包括:我想用AVR的一个定时器中断来控制舵机的左右45度转动,请问中断程序怎么写呢、怎么用按键控制舵机的程序、初学单片机,指导MG995舵机中断程序编写,占空比怎么弄,想用两个按键控制舵机开合状态,求程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zz/9775612.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存