基于C51的多路舵机PWM控制原理(有程序)
c51控制6路舵机51单片机超高精度6路舵机程序

#include “reg52.h”#define uchar unsigned char#define uint unsigned intP0M1=0X00;P0M0=0XFF;设置P0 为强推挽输出sbit servo0=P0^0;sbit servo1=P0^1;sbit servo2=P0^2;sbit servo3=P0^3;sbit servo4=P0^4;sbit servo5=P0^5;sbit servo6=P0^6;sbit servo7=P0^7;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计数功能串口初始化,晶振11.0592,波特率9600,使能了串口中断void Com_Init(){TMOD = 0x20; 用定时器设置串口波特率TH1=0xFD; (32129600)=253 (FD)TL1=0xFD;同上TR1=1;定时器1开关打开REN=1; 开启允许串行接收位SM0=0;串口方式,8位数据SM1=1;同上EA=1; 开启总中断ES=1; 串行口中断允许位}功能舵机PWM中断初始化void Timer0Init(){0度=0.5ms, 45度=1ms, 90度=1.5ms, 135度=2ms, 180度=2.5ms2.5 ms初始值F700, (12n11059200=2.51000, n=2304, X=65536-2304=63232 F700)TMOD = 0x01; 使用模式1,16位定时器,使用符号可以在使用多个定时器时不受影响TH0=-ms2_5Con8; 给定初值,17ms中断TL0=-ms2_5Con;EA=1; 总中断打开ET0=1; 定时器0中断打开TR0=1; 定时器0开关打开}功能舵机PWM中断, 舵机控制函数周期为20ms 一个循环20MS = 82.5msvoid 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; case 3 servo1=1; TH0=-pwm[1]8; TL0=-pwm[1]; break;case 4 servo1=0; TH0=-(ms2_5Con-pwm[1])8; TL0=-(ms2_5Con-pwm[1]); break; case 5 servo2=1; TH0=-pwm[2]8; TL0=-pwm[2]; break;case 6 servo2=0; TH0=-(ms2_5Con-pwm[2])8; TL0=-(ms2_5Con-pwm[2]); break; case 7 servo3=1; TH0=-pwm[3]8; TL0=-pwm[3]; break;case 8 servo3=0; TH0=-(ms2_5Con-pwm[3])8; TL0=-(ms2_5Con-pwm[3]); break; case 9 servo4=1; TH0=-pwm[4]8; TL0=-pwm[4]; break;case 10 servo4=0; TH0=-(ms2_5Con-pwm[4])8; TL0=-(ms2_5Con-pwm[4]); break;case 11 servo5=1; TH0=-pwm[5]8; TL0=-pwm[5]; break;case 12 servo5=0; TH0=-(ms2_5Con-pwm[5])8; TL0=-(ms2_5Con-pwm[5]); break; case 13 servo6=1;TH0=-pwm[6]8; TL0=-pwm[6]; break;case 14 servo6=0;TH0=-(ms2_5Con-pwm[6])8; TL0=-(ms2_5Con-pwm[6]); break;case 15 servo7=1;TH0=-pwm[7]8; TL0=-pwm[7]; break;case 16 servo7=0;TH0=-(ms2_5Con-pwm[7])8; TL0=-(ms2_5Con-pwm[7]); break; default TH0=0xff; TL0=0x80; pwm_flag=0;}pwm_flag++;}void SetSteeringGear(uchar i, uchar val){uint a = (val+46)10;if(ams0_5Con)a=ms0_5Con;if(ams2_5Con)a=ms2_5Con;pwm[i]=a;serVal[0]=255; 清除缓存}void SteeringGearUp(uchar i){if(pwm[i]ms0_5Con)pwm[i]=pwm[i]-10;}void SteeringGearDown(uchar i){if(pwm[i]ms2_5Con)pwm[i]=pwm[i]+10;}功能串口中断接收数据void ser() interrupt 4{serVal[0]=serVal[1];serVal[1]=SBUF;RI=0;串口中断清0}函数功能:主函数void main(){bit started=0; 路由是否已经启动完毕Com_Init();串口初始化Timer0Init();舵机初始化while(1){if(serVal[0]=='w' && serVal[1]=='d'){started=1; 路由启动最后会出现:ar71xx-wdt,由此判断路由已经启动}if(started){if(serVal[0]==0){switch(serVal[1]){case 'A' SteeringGearUp(0); break; case 'B' SteeringGearDown(0); break; case 'C' SteeringGearUp(1); break; case 'D' SteeringGearDown(1); break; case 'E' SteeringGearUp(2); break; case 'F' SteeringGearDown(2); break; case 'G' SteeringGearUp(3); break; case 'H' SteeringGearDown(3); break; case 'I' SteeringGearUp(4); break; case 'J' SteeringGearDown(4); break; case 'K' SteeringGearUp(5); break; case 'L' SteeringGearDown(5); break; defaultbreak;}serVal[0]=255; 清除缓存}else if(serVal[0]==1){ SetSteeringGear(0,serVal[1]);}else if(serVal[0]==2){ SetSteeringGear(1,serVal[1]);}else if(serVal[0]==3){ SetSteeringGear(2,serVal[1]);}else if(serVal[0]==4){ SetSteeringGear(3,serVal[1]);}else if(serVal[0]==5){ SetSteeringGear(4,serVal[1]);}else if(serVal[0]==6){ SetSteeringGear(5,serVal[1]);}}}}。
基于51单片机的舵机控制原理

基于51单片机的舵机控制原理网络上流行的对舵机的误解文章太多太多!而且很怪异的是——很多主流的意识是错误的下面这篇文章,我大致看过,是符合科学原理的,想学习知识的可以看看。
注意吸收知识,要由根本上去分析,而不是以讹传讹!否则你必定就象很多人一样去坚守“数码舵机比模拟舵机快”这个完全错误的观点,呵呵,那会被真正掌握知识的人暗地里面耻笑的数码舵机常见问题原理分析及解决:一、数码舵机与模拟舵机的区别传统模拟舵机和数字比例舵机(或称之为标准舵机)的电子电路中无MCU微控制器,一般都称之为模拟舵机。
老式模拟舵机由功率运算放大器等接成惠斯登电桥,根据接收到模拟电压控制指令和机械连动位置传感器(电位器)反馈电压之间比较产生的差分电压,驱动有刷直流电机伺服电机正/反运转到指定位置。
数字比例舵机是模拟舵机最好的类型,由直流伺服电机、直流伺服电机控制器集成电路(IC),减速齿轮组和反馈电位器组成,它由直流伺服电机控制芯片直接接收PWM(脉冲方波,一般周期为20ms,脉宽1~2 ms,脉宽1 ms为上限位置,1.5ms为中位,2ms为下限位置)形式的控制驱动信号,迅速驱动电机执行位置输出,直至直流伺服电机控制芯片检测到位置输出连动电位器送来的反馈电压与PWM控制驱动信号的平均有效电压相等,停止电机,完成位置输出。
数码舵机电子电路中带MCU微控制器故俗称为数码舵机,数码舵机凭借比之模拟舵机具有反应速度更快,无反应区范围小,定位精度高,抗干扰能力强等优势已逐渐取代模拟舵机在机器人、航模中得到广泛应用。
数码舵机设计方案一般有两种:一种是MCU+直流伺服电机+直流伺服电机控制器集成电路(IC)+减速齿轮组+反馈电位器的方案,以下称为方案1,另一种是MCU+直流伺服电机+减速齿轮组+反馈电位器的方案,以下称为方案2。
市面上加装数码驱动板把模拟舵机改数码舵机属方案1。
二、舵机电机调速原理及如何加快电机速度常见舵机电机一般都为永磁直流电动机,如直流有刷空心杯电机。
51单片机一个定时器控制多路舵机

#ifndef __interrupt0_H__#define __interrupt0_H__void interrupt0() //STM中断服务子程序{_t2af = 0 ;switch (cnt){case 0:PWMOUT_2 = PWMOUT_3 = PWMOUT_4 = PWMOUT_5 = PWMOUT_6 = 0;PWMOUTbuf_1 = (PWMbuf - PWMOUTbuf_1);_tm2al = PWMOUTbuf_1 & 0x00ff;_tm2ah = PWMOUTbuf_1 >>8 ; //重新定义计数初值if( PWMOUTbuf_1 >= PWMOUTbufmin1 && PWMOUTbuf_1 <= PWMOUTbufmax1){PWMOUTbuf_1 = PWMOUTcnt_1; PWMOUT_1 = 1;}else{PWMOUTbuf_1 = PWMbuf-PWMOUTcnt_1; PWMOUT_1 = 0 ; cnt = 1;} //判断脉宽是否在正常范围之内break;case 1:PWMOUT_1 = PWMOUT_3 = PWMOUT_4 = PWMOUT_5 = PWMOUT_6 = 0;PWMOUTbuf_2 = (PWMbuf - PWMOUTbuf_2);_tm2al = PWMOUTbuf_2 & 0x00ff; //重新定义计数初值_tm2ah = PWMOUTbuf_2 >> 8;if(PWMOUTbuf_2 >= PWMOUTbufmin1 && PWMOUTbuf_2 <= PWMOUTbufmax1){PWMOUTbuf_2 = PWMOUTcnt_2; PWMOUT_2 = 1;}else{PWMOUTbuf_2 = PWMbuf-PWMOUTcnt_2;PWMOUT_2 = 0;cnt = 2;} //判断脉宽是否在正常范围之内break;case 2:PWMOUT_1 = PWMOUT_2 = PWMOUT_4 = PWMOUT_5 = PWMOUT_6 = 0;PWMOUTbuf_3 = (PWMbuf - PWMOUTbuf_3);_tm2al = PWMOUTbuf_3 & 0x00ff; //重新定义计数初值_tm2ah = PWMOUTbuf_3 >> 8;if(PWMOUTbuf_3 >= PWMOUTbufmin1 && PWMOUTbuf_3 <= PWMOUTbufmax1){PWMOUTbuf_3 = PWMOUTcnt_3; PWMOUT_3 = 1;}else{PWMOUTbuf_3 = PWMbuf-PWMOUTcnt_3;PWMOUT_3 = 0;cnt = 3;} //判断脉宽是否在正常范围之内break;case 3:PWMOUT_1 = PWMOUT_2 = PWMOUT_3 = PWMOUT_5 = PWMOUT_6 = 0;PWMOUTbuf_4 = (PWMbuf - PWMOUTbuf_4);_tm2al = PWMOUTbuf_4 & 0x00ff;_tm2ah = PWMOUTbuf_4 >>8 ; //重新定义计数初值if( PWMOUTbuf_4 >= PWMOUTbufmin1 && PWMOUTbuf_4 <= PWMOUTbufmax1){PWMOUTbuf_4 = PWMOUTcnt_4; PWMOUT_4 = 1;}else{PWMOUTbuf_4 = PWMbuf-PWMOUTcnt_4; PWMOUT_4 = 0;cnt = 4;} //判断脉宽是否在正常范围之内break;case 4:PWMOUT_1 = PWMOUT_2 = PWMOUT_3 = PWMOUT_4 = PWMOUT_6 = 0;PWMOUTbuf_5 = (PWMbuf - PWMOUTbuf_5);_tm2al = PWMOUTbuf_5 & 0x00ff; //重新定义计数初值_tm2ah = PWMOUTbuf_5 >> 8;if(PWMOUTbuf_5 >= PWMOUTbufmin1 && PWMOUTbuf_5 <= PWMOUTbufmax1){PWMOUTbuf_5 = PWMOUTcnt_5; PWMOUT_5 = 1;}else{PWMOUTbuf_5 = PWMbuf-PWMOUTcnt_5;PWMOUT_5 = 0;cnt = 5;} //判断脉宽是否在正常范围之内break;case 5:PWMOUT_1 = PWMOUT_2 = PWMOUT_3 = PWMOUT_4 = PWMOUT_5 = 0;PWMOUTbuf_6 = (PWMbuf - PWMOUTbuf_6);_tm2al = PWMOUTbuf_6 & 0x00ff; //重新定义计数初值_tm2ah = PWMOUTbuf_6 >> 8;if(PWMOUTbuf_6 >= PWMOUTbufmin1 && PWMOUTbuf_6 <= PWMOUTbufmax1){PWMOUTbuf_6 = PWMOUTcnt_6; PWMOUT_6 = 1;}else{PWMOUTbuf_6 = PWMbuf-PWMOUTcnt_6;PWMOUT_6 = 0;cnt = 0;} //判断脉宽是否在正常范围之内break;default: break;}}#endif。
51单片机 PWM电位器控制舵机

/*-----------------------------------------------名称:IIC协议 PCF8591ADDA转换内容:此程序通过IIC协议对DAAD芯片操作,读取电位器的电压,并输出模拟量,用LED亮度渐变指示,晶体选用12MHz------------------------------------------------*/#include"reg52.h"#include <intrins.h> //包含NOP空指令函数_nop_();#define AddWr 0x90 //写数据地址#define AddRd 0x91 //读数据地址sbit Sda=P1^2; //定义总线连接端口sbit Scl=P1^1;sbit control_signal=P1^5;data unsigned int Display[8];//定义临时存放数码管数值unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段数共阴码管段码表unsigned int ADtemp; //定义全局变量unsigned int high,low;static unsigned int count1;/*------------------------------------------------延时程序------------------------------------------------*/void mDelay(unsigned char j){unsigned int i;for(;j>0;j--){for(i=0;i<125;i++){;}}}/*------------------------------------------------初始化定时器0------------------------------------------------*/void Init_Timer0(void){TMOD |=0x01; //定时器设置 0.1ms in 11.0592M crystal TH0=(65536-78)/256;TL0=(65536-78)%256; //定时0.1mSET0=1;//定时器中断打开EA=1;//总中断TR0=1; //启动定时器0}/*------------------------------------------------启动IIC总线------------------------------------------------*/void Start(void)Sda=1;_nop_();Scl=1;_nop_();Sda=0;_nop_();Scl=0;}/*------------------------------------------------停止IIC总线------------------------------------------------*/ void Stop(void){Sda=0;_nop_();Scl=1;_nop_();Sda=1;_nop_();Scl=0;}/*------------------------------------------------应答IIC总线------------------------------------------------*/ void Ack(void){Sda=0;_nop_();Scl=1;_nop_();Scl=0;_nop_();}/*------------------------------------------------非应答IIC总线------------------------------------------------*/ void NoAck(void){Sda=1;_nop_();Scl=1;_nop_();Scl=0;_nop_();}/*------------------------------------------------发送一个字节------------------------------------------------*/ void Send(unsigned char Data){unsigned char BitCounter=8;unsigned char temp;do{temp=Data;Scl=0;_nop_();if((temp&0x80)==0x80)Sda=1;elseSda=0;Scl=1;temp=Data<<1;Data=temp;BitCounter--;}while(BitCounter);Scl=0;}/*------------------------------------------------读入一个字节并返回------------------------------------------------*/ unsigned char Read(void){unsigned char temp=0;unsigned char temp1=0;unsigned char BitCounter=8;Sda=1;do{Scl=0;_nop_();Scl=1;_nop_();if(Sda)temp=temp|0x01;elsetemp=temp&0xfe;if(BitCounter-1){temp1=temp<<1;temp=temp1;}BitCounter--;}while(BitCounter);return(temp);}/*------------------------------------------------读取AD模数转换的值,有返回值------------------------------------------------*/unsigned int ReadADC(unsigned char Chl){unsigned int Data;Start(); //启始信号Send(AddWr);//0x90Ack();Send(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加 //Chl的值分别为0、1、2、3,分别代表1-4通道Ack();Start();Send(AddRd); //读入地址Ack();Data=Read(); //读数据Scl=0;NoAck();Stop();return Data; //返回值}/******************************************************************//* 主程序 *//******************************************************************/void main(){Init_Timer0();while(1){unsigned int angle;ADtemp=ReadADC(0); //ADtemp的取值范围是0-255,定时的时间范围是0.5-2.5ms high=65075-7.2*ADtemp; //( high=65035-7.8*ADtemp;12MHz)(65535-(460+7.2*ADtemp 11.0592MHz) low=47563+7.2*ADtemp; // ( low=46035+7.8*ADtemp; )( 65535-(17972-7.2*ADtemp 11.0592MHz )angle=ADtemp*0.7;Display[0]=Datatab[angle/100];//处理0通道电压显示Display[1]=Datatab[(angle%100)/10];Display[2]=Datatab[angle%10];while(1){P0=Display[count1];//用于动态扫描数码管P2=count1;mDelay(1);count1++;if(count1==3) //表示扫描8个数码管{count1=0;break;}}}}/******************************************************************//* 定时器中断函数,需要更改/******************************************************************/void tim(void) interrupt 1 using 1{static unsigned char count;if (!count){control_signal = 1; //给高电平TH0=high/256;TL0=high%256; //定时0.05mS,经过示波器的测量}else{control_signal=0 ;TH0=low/256;TL0=low%256; //定时0.05mS,经过示波器的测量}count=~count;}。
基于C51单片机的直流电机PWM调速控制(包含原理图及C源代码)

基于C51单片机的直流电机PWM调速控制--SQ这是最近一阶段自己学习所获,现分享与大家。
这里采用A T89C52单片机做主控制芯片,实现两路直流电机的PWM调速控制,另外还可以实现转向、显示运行时间、显示档位等注:考虑小直流电机自身因素,调速范围仅设有四级电路原理图:C语言程序源代码:/******************** 硬件资源分配*********************/数码管:显示电机状态(启停、正反、速度)、运行时间、是否转弯按键:K4 启动/暂停K3 正反转/转弯允许K2 加速/左转/运行时间清零K1 减速/右转/停止定时器:T0 数码管动态显示,输出PWMT1 运行时间记录********************************************************//*******主程序文件PWM.c******/#include <reg52.h>#include "Afx.h"#include "Config.c"#define CIRCLE 5 //脉冲周期//按键定义uchar key,key_tmp=0, _key_tmp=0;//显示定义uchar LedState=0xF0; //LED显示标志,0xF0不显示,Ox00显示uchar code LED_code_d[4]={0xe0,0xd0,0xb0,0x70}; //分别选通1、2、3、4位uchar dispbuf[4]={0,0,0,0}; //待显示数组uchar dispbitcnt=0; //选通、显示的位uchar mstcnt=0;uchar Centi_s=0,Sec=0,Min=0; //分、秒、1%秒//程序运行状态标志bit MotState=0; //电机启停标志bit DirState=0; //方向标志0前,1后uchar State1=-1;uchar State2=-1;uchar State3=0;uchar State4=-1;uchar LSpeed=0;uchar RSpeed=0;//其他uint RunTime=0;uint RTime_cnt=0;uint LWidth;uint RWidth; //脉宽uint Widcnt=1;uint Dispcnt;//函数声明void key_scan(void);void DisBuf(void);void K4(void);void K3(void);void K2(void);void K1(void);void disp( uchar H, uchar n );void main(void){P1|=0xF0;EA=1;ET0=1;ET1=1;TMOD=0x11;TH0=0xFC;TL0=0x66; //T0,1ms定时初值TH1=0xDB;TL1=0xFF; //T1,10ms定时初值TR0=1;Widcnt=1;while(1){key_scan();switch(key){case 0x80: K1(); break;case 0x40: K2(); break;case 0x20: K3(); break;case 0x10: K4(); break;default:break;}key=0;DisBuf();LWidth=LSpeed;RWidth=RSpeed;}}//按键扫描**模拟触发器防抖void key_scan(void){key_tmp=(~P3)&0xf0;if(key_tmp&&!_key_tmp) //有键按下{key=(~P3)&0xf0;}_key_tmp=key_tmp ;}//按键功能处理/逻辑控制void K4(void){if(State4==-1){State4=1;TR1=1;dispbuf[3]=1;LedState=0x00; //打开LEDMotState=1; //打开电机LSpeed=1;RSpeed=1; //初速设为1}else if(State4==1){State4=0;TR1=0;MotState=0; //关闭电机}else if(State4==0){MotState=1;if(State3==0){State4=1;TR1=1;}else if(State3==1){LSpeed=2;RSpeed=2;}}}void K3(void){if(State4==1)DirState=!DirState;if(State4==0){if(State3==0){State3=1; //可以转向标志1可以,0不可以TR1=1;dispbuf[3]=9;MotState=1;LSpeed=2;RSpeed=2;}else if(State3==1){State3=0;TR1=0;dispbuf[3]=0;MotState=0;}}}void K2(void){if(State4==1&&LSpeed<4&&RSpeed<4){LSpeed++;RSpeed++;}else if(State4==0){if(State3==0){//State4=-1;//LedState=0xF0;MotState=0;Sec=0;Min=0;}else if(State3==1&&LSpeed<4&&RSpeed<4){//TurnState=0;LSpeed=2;RSpeed++;}}}void K1(void){if(State4==1&&LSpeed>1&&RSpeed>1){LSpeed--;RSpeed--;}else if(State4==0){if(State3==0){State4=-1;LedState=0xF0;MotState=0;}else if(State3==1&&LSpeed<4&&RSpeed<4){//TurnState=1;LSpeed++;RSpeed=2;}}}//显示预处理void DisBuf(void){if(RTime_cnt==100){Sec++;RTime_cnt=0;}if(Sec==60){Min++;Sec=0;}if(State4==1){dispbuf[0]=Sec%10;dispbuf[1]=Sec/10;dispbuf[2]=Min;if(!DirState) //正转dispbuf[3]=LSpeed;if(DirState) //反转dispbuf[3]=LSpeed+4;}if(State4==0){if(State3==0){dispbuf[0]=Sec%10;dispbuf[1]=Sec/10;dispbuf[2]=Min;dispbuf[3]=0;}if(State3==1){dispbuf[0]=RSpeed;dispbuf[1]=LSpeed;dispbuf[2]=Min;dispbuf[3]=9;}}}//LED驱动void disp( uchar H, uchar n ){P1=n;P1|=LedState ;P1|=LED_code_d[H];}//T0中断**显示/方波输出void Time_0() interrupt 1{TH0=0xFC;TL0=0x66;Widcnt++;Dispcnt++;//电机驱动/方波输出if(Widcnt>CIRCLE){Widcnt=1;}if(Widcnt<=LWidth)LMot_P=!DirState&&MotState;elseLMot_P=DirState&&MotState;LMot_M=DirState&&MotState;if(Widcnt<=RWidth)RMot_P=!DirState&&MotState;elseRMot_P=DirState&&MotState;RMot_M=DirState&&MotState;//显示if(Dispcnt==5){disp(dispbitcnt,dispbuf[dispbitcnt]);dispbitcnt++;if(dispbitcnt==4){dispbitcnt=0;}Dispcnt=0;}}//T1中断**运行时间void Time_1() interrupt 3{TH1=0xDB;TL1=0xFF;RTime_cnt++;}/******配置文件Afx.h******/#ifndef _AFX_#define _AFX_typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;#endif/******IO配置文件Config.c******/#ifndef _Config_#define _Config_#include "Afx.h"#include <reg52.h>//显示定义sbit led=P3^2;//电机引脚定义sbit LMot_P=P2^2; sbit LMot_M=P2^3; sbit RMot_P=P2^0; sbit RMot_M=P2^1;#endif。
51单片机 舵机控制程序

51单片机舵机控制程序题目:基于51单片机的舵机控制程序设计与实现第一章:引言1.1 研究背景51单片机是一种广泛应用于嵌入式系统中的微控制器,具有成本低、功耗低、可靠性高等优点。
而舵机是一种能够控制角度的电机装置,广泛应用于机器人、航模和自动化设备等领域。
本章旨在探讨基于51单片机的舵机控制程序设计与实现的意义和必要性。
1.2 研究目的本研究的主要目的在于设计并实现一套稳定、高效的舵机控制程序,为使用51单片机的嵌入式系统提供角度控制功能。
通过本研究,可以提高舵机控制的精度和稳定性,拓展舵机的应用领域。
第二章:51单片机舵机控制程序的设计2.1 硬件设计根据舵机的控制特点,我们需要通过PWM信号控制舵机转动的角度。
在硬件设计上,我们需要使用51单片机的定时器功能产生PWM信号,并通过IO口输出给舵机。
具体的设计方案包括选择合适的定时器、设置定时器的工作模式和频率等。
2.2 软件设计在软件设计上,我们需要通过编写51单片机的控制程序实现舵机的控制。
具体的设计流程包括:(1)初始化:设置定时器的工作模式和频率,配置IO口的输出模式。
(2)角度控制:根据舵机的角度范围和控制精度,将目标角度转换为占空比,并通过PWM信号控制舵机转动到目标角度。
(3)稳定性优化:通过对定时器周期和占空比的调整,优化舵机的稳定性,减小舵机的误差。
第三章:51单片机舵机控制程序的实现3.1 硬件搭建在实现阶段,我们需要根据硬件设计方案选购相应的硬件元件,并将其搭建成一个完整的舵机控制系统。
具体的搭建过程包括:(1)选购舵机和51单片机等硬件元件,并连接相关的信号线。
(2)按照硬件设计方案,搭建并调试舵机控制系统。
3.2 软件编写在软件实现阶段,我们需要使用51单片机的编程语言(如C语言或汇编语言)编写舵机控制程序,并通过编译和烧录等步骤将程序下载到51单片机中。
具体的编写过程包括:(1)按照软件设计方案,编写舵机控制程序的相关函数和逻辑。
PWM波控制舵机原理

舵机的控制信号是 PWM 信号,利用占空比的变化,改变舵机的位置。
有个很有趣的技术话题可以稍微提一下,就是 BA6688 是有 EMF 控制的,主要用途是控制在高速时候电机最大转速。
原理是这样的:收到 1 个脉冲以后,BA6688 内部也产生 1 个以 5K 电位器实际电压为基准的脉冲,2 个脉冲比较以后展宽,输出给驱动使用。
当输出足够时候,马达就开始加速,马达就能产生 EMF,这个和转速成正比的。
因为取的是中心电压,所以正常不能检测到的,但是运行以后就电平发生倾斜,就能检测出来。
超过 EMF判断电压时候就减小展宽,甚至关闭,让马达减速或者停车。
这样的好处是可以避免过冲现象(就是到了定位点还继续走,然后回头,再靠近)。
一些国产便宜舵机用的便宜的芯片,就没有 EMF 控制,马达、齿轮的机械惯性就容易发生过冲现象,产生抖舵电源线和地线用于提供舵机内部的直流电机和控制线路所需的能源.电压通常介于 4~6V,一般取 5V。
注意,给舵机供电电源应能提供足够的功率。
控制线的输入是一个宽度可调的周期性方波脉冲信号,方波脉冲信号的周期为 20 ms(即频率为 50 Hz)。
当方波的脉冲宽度改变时,舵机转轴的角度发生改变,角度变化与脉冲宽度的变化成正比。
某型舵机的输出轴转角与输入信号的脉冲宽度之间的关系可用图 3 来表示。
标准的微型伺服马达有三条控制线,分别为:电源、地及控制。
电源线与地线用于提供内部的直流马达及控制线路所需的能源,电压通常介于 4V-6V 之间,该电源应尽可能与处理系统的电源隔离(因为伺服马达会产生噪音)。
甚至小伺服马达在重负载时也会拉低放大器的电压,所以整个系统的电源供应的比例必须合理。
控制线输入一个周期性的正向脉冲信号,这个周期性脉冲信号的高电平时间通常在 1ms-2ms 之间。
而低电平时间应在 5ms 到 20ms 间,并不很严格。
下表表示出一个典型的 20ms 周期性脉冲的正脉冲宽度与微型伺服马达的输出臂位置的关系:舵机工作原理1、概述舵机最早出现在航模运动中。
基于51单片机的舵机控制

基于51单片机的舵机控制2010-05-2319:48基于单片机的舵机控制方法具有简单、精度高、成本低、体积小的特点,并可根据不同的舵机数量加以灵活应用在机器人机电控制系统中,舵机控制效果是性能的重要影响因素・舵机可以在微机电系统和航模中作为基本的输出执行机构,其简单的控制和输出使得单片机系统非常容易与之接口舵机是一种位置伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统•其工作原理是:控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压・它内部有一个基准电路,产生周期为20m6宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出口最后,电压差的正负输出到电机驱动芯片决定电机的正反转・当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动*舵机的控制信号是PWM1号,利用占空比的变化改变舵机的位置・一般舵机的控制要求如图1所示力腌8脉维=2ins图1舵机的控制要求单片机实现舵机转角控制可以使用FPGA模拟电路、单片机来产生舵机的控制信号,但FPG腋本高且电路复杂・对于脉宽调制信号的脉宽变换,常用的一种方法是采用调制信号获取有源滤波后的直流电压,但是需要50Hz(周期是20ms)的信号,这对运放器件的选择有较高要求,从电路体积和功耗考虑也不易采用口5mV以上的控制电压的变化就会引起舵机的抖动,对于机载的测控系统而言,电源和其他器件的信号噪声都远大于5mV所以滤波电路的精度难以达到舵机的控制精度要求也可以用单片机作为舵机的控制单元,使PWM&号的脉冲宽度实现微秒级的变化,从而提高舵机的转角精度・单片机完成控制算法,再将计算结果转化为PWM1号输出到舵机,由于单片机系统是一个数字系统,其控制信号的变化完全依靠硬件计数,所以受外界干扰较小,整个系统工作可靠单片机系统实现对舵机输出转角的控制,必须首先完成两个任务:首先是产生基本的PW惆期信号,本设计是产生20ms的周期信号;其次是脉宽的调整,即单片机模拟PWM1号的输出,并且调整占空比・当系统中只需要实现一个舵机的控制,采用的控制方式是改变单片机的一个定时器中断的初值,将20ms分为两次中断执行,一次短定时中断和一次长定时中断“这样既节省了硬件电路,也减少了软件开销,控制系统工作效率和控制精度都很高具体的设计过程:例如想让舵机转向左极限的角度,它的正脉冲为2ms,则负脉冲为20ms-2ms=18ms所以开始时在控制口发送高电平,然后设置定时器在2ms后发生中断,中断发生后,在中断程序里将控制口改为低电平,并将中断时间改为18ms 再过18ms进入下一次定时中断,再将控制口改为高电平,并将定时器初值改为2m§等待下次中断到来,如此往复实现PWM1号输出到舵机・用修改定时器中断初值的方法巧妙形成了脉冲信号,调整时间段的宽度便可使伺服机灵活运动为保证软件在定时中断里采集其他信号,并且使发生PWM1号的程序不影响中断程序的运行(如果这些程序所占用时间过长,有可能会发生中断程序还未结束,下次中断又到来的后果),所以需要将采集信号的函数放在长定时中断过程中执行,也就是说每经过两次中断执行一次这些程序,执行的周期还是20ms软件流程如图2所示*开足附中断改变定时时间中断程序(中断返图2产生PWMf号的软件流程如果系统中需要控制几个舵机的准确转动,可以用单片机和计数器进行脉冲计数产生PWM1号脉冲计数可以利用51单片机的内部计数器来实现,但是从软件系统的稳定性和程序结构的合适性看,宜使用外部的计数器,还可以提高CPU勺工作效率・实验后从精度上考虑,对于FUTAB麻列的接收机,当采用1MHz勺外部晶振时,其控制电压幅值的变化为0.6mV,而且不会出现误差积累,可以满足控制舵机的要求•最后考虑数字系统的离散误差,经估算误差的范围在±0.3%内,所以采用单片机和8253、8254这样的计数器芯片的PWM1号产生电路是可靠的•图3是硬件连接图图3PWA信号的计数和输出电路(点击放大)基于8253产生PWM1号的程序主要包括三方面内容:一是定义8253寄存器的地址,二是控制字的写入,三是数据的写入•软件流程如图4所示,具体代码如下・//关键程序及注释://定时器T0中断,向8253发送控制字和数据voidT0Int()interrupt1(TH0=0xB1;TL0=0xE0;//20ms的时钟基准//先写入控制字,再写入计数值SERVO0=0x30;//选择计数器0,写入控制字PWM0=BUF0L;〃先写低,后写高PWM0=BUF0H;SERVO1=0x70;//选择计数器1,写入控制字PWM1=BUF1L;PWM1=BUF1H;SERVO2=0xB0;//选择计数器2,写入控制字PWM2=BUF2L;PWM2=BUF2H;}定义8253寄存器地址图4基于8253产生PWAS号的软件流程当系统的主要工作任务就是控制多舵机的工作,并且使用的舵机工作周期均为20ms时,要求硬件产生的多路PW械的周期也相同・使用51单片机的内部定时器产生脉冲计数,一般工作正脉冲宽度小于周期的1/8,这样可以在1个周期内分时启动各路PW瞰的上升沿,再利J用定时器中断T0确定各路PW瞰的输出宽度,定时器中断T1控制20ms的基准时间<■第1次定时器中断T0按20ms的1/8设置初值,并设置输出I/O口,第1次T0定时中断响应后,将当前输出I/O口对应的引脚输出置高电平,设置该路输出正脉冲宽度,并启动第2次定时器中断,输出I/O口指向下一个输出口•第2次定时器定时时间结束后,将当前输出引脚置低电平,设置此中断周期为20ms的1/8减去正脉冲的时间,此路PWM言号在该周期中输出完毕,往复输出•在每次循环的第16次(2X8=16)中断实行关定时中断T0的操作,最后就可以实现8路舵机控制信号的输出也可以采用外部计数器进行多路舵机的控制,但是因为常见的8253、8254芯片都只有3个计数器,所以当系统需要产生多路PWM1号时,使用上述方法可以减少电路,降低成本,也可以达到较高的精度•调试时注意到由于程序中脉冲宽度的调整是靠调整定时器的初值,中断程序也被分成了8个状态周期,并且需要严格的周期循环,而且运行其他中断程序代码的时间需要严格把握在实际应用中,采用51单片机简单方便地实现了舵机控制需要的PWMF号・对机器人舵机控制的测试表明,舵机控制系统工作稳定,PWM■空比(0.5〜2.5ms的正脉冲宽度)和舵机的转角(-90°〜90°)线性度较好.。
c51单片机C语言编写的PWM程序

89c51单片机C语言编写的P W M程序(共3页)-本页仅作为预览文档封面,使用时请删除本页-89c51单片机C语言编写的PWM程序PWM, 单片机, C语言, 程序, 编写分享到:新浪微博 QQ空间开心网人人网说明:本程序使用STC89C52RC单片机,晶振,要使用本程序需要自己修改,我是用来控制直流电机的,外接了L298驱动电路,有问题或意见请回复,谢谢^_^#include ""#include ""转;speed<0.反转(-100~100)调用:extern int abs(int val); 取绝对值返回:/******************************************************************/ void motor(char speed1,char speed2){ //==============左边电机============= if (speed1>0) { IN1 =0;IN2 =1;//正转} else if (speed1<0) { IN1 =1;IN2 =0;//反转}//==============右边电机============= if (speed2>0) { IN3 =1;IN4 =0;//正转} else if (speed2<0) { IN3 =0;IN4 =1;//反转}}/******************************************************************名称:motor_PWM();功能:PWM占空比输出参数:无调用:无返回:无/******************************************************************/void motor_PWM (){ uchar PWM_abs1; uchar PWM_abs2;PWM_abs1=MOTO_speed1; PWM_abs2=MOTO_speed2;if (PWM_abs1>PWMAnd) ENA=1; //左边电机占空比输出else ENA=0; if (PWM_abs2>PWMAnd) ENB=1; //右边电机占空比输出else ENB=0; if (PWMAnd>=PWM_COUST) PWMAnd=0; //PWM计数清零else PWMAnd+=1;}/******************************************************************名称:void TIME_Init ();功能:定时器初始化指令:调用:无返回:无/******************************************************************/void TIME_Init (){//=========定时器T2初始化 PWM==================T2CON = 0x00;T2MOD = 0x00;RCAP2H = 0xff; //定时RCAP2L = 0x47; TH2 = 0xff; TL2 = 0x47; ET2 = 1; //定时器2中断开TR2 = 1; //PWM定时器关,PWM周期为10ms }/******************************************************************名称:void PWM_Time2 () interrupt 5功能:T2中断,PWM控制参数:调用:motor_PWM();//PWM占空比输出返回:/******************************************************************/ void PWM_Time2 () interrupt 5{ TR2 = 0; TF2 = 0; ET2 = 0; //定时器0中断禁止motor_PWM();//PWM占空比输出ET2 = 1; //定时中断0开启TR2 = 1;}main(){TIME_Init () ;motor(50,50);//左右电机的转速都是50}。
51单片机控制多路舵机

51单片机控制多路舵机第一章:引言(200-250字)51单片机是一种常用的微型控制器,广泛应用于各种电子控制系统中。
而舵机作为一种常见的执行器,被广泛应用于机器人、航模等领域。
本论文旨在探讨如何使用51单片机实现多路舵机控制,并介绍其应用。
第二章:多路舵机控制的原理与方法(300-350字)2.1 舵机的工作原理舵机是一种能够实现角度精确控制的电机。
其核心部件是一个内置了电机、减速装置和角度反馈装置的封装,通过输入PWM信号来控制舵机的转动角度。
2.2 51单片机实现PWM信号输出51单片机通过定时器和PWM相关寄存器可以产生需要的PWM信号。
通过改变占空比来控制舵机的角度,实现舵机的转动。
2.3 多路舵机的控制通过引出多个PWM输出引脚,可以实现多路舵机的控制。
通过对每个舵机的PWM信号进行编码和解码,可以实现对多路舵机的独立控制。
第三章:实验与结果(300-350字)3.1 实验原理在实验中,我们使用了一款51单片机开发板和多路舵机,通过编写相应的程序,控制51单片机输出多路PWM信号,从而实现对多路舵机的控制。
3.2 实验步骤首先,将多路舵机连接到51单片机的相应IO口,并连接电源。
然后,编写相应的51单片机程序,配置定时器和PWM输出引脚。
接着,通过改变相应PWM引脚的占空比,控制舵机的转动角度。
3.3 实验结果我们成功地控制了多路舵机的转动。
通过改变不同舵机对应的PWM引脚的占空比,实现了舵机的不同角度转动。
实验结果表明,我们所设计的多路舵机控制系统是可行的。
第四章:结论与展望(150-200字)在本论文中,我们研究了51单片机控制多路舵机的原理和方法,并进行了相应的实验验证。
实验结果表明,我们所设计的方案可以有效地控制多路舵机的转动。
通过本论文的研究,我们可以发现,使用51单片机控制多路舵机具有一定的优势,比如成本低、可编程性强等。
然而,本研究还有一些局限性。
例如,目前我们只控制了少量的舵机,没有涉及到大规模的控制。
51 舵机控制程序

51 舵机控制程序章节一:绪论舵机是一种常见的电机装置,广泛应用于机械设备、船舶、航空器等领域。
其主要功能是使机械部件可以按照一定的角度进行旋转或转动。
舵机的控制十分重要,可以通过控制舵机的角度实现对装置的角度或位置的精细调节。
随着现代技术的进步,电子舵机逐渐取代了传统的机械舵机,成为控制系统中的重要组成部分。
本论文旨在探讨51单片机在舵机控制中的应用。
章节二:舵机的工作原理和性能特点舵机是一种闭环控制系统,其工作原理是通过对电机的驱动电压进行调整,控制电机的转向和转动角度。
一个舵机主要由电机、减速器、位置反馈装置和控制电路组成。
位置反馈装置可以感知电机当前的位置,并向控制电路发送反馈信号。
电机转动一定角度后,位置反馈装置会将实际位置信息反馈给控制电路,控制电路根据反馈信号进行调整,将舵机转动到目标位置。
舵机的性能特点主要包括转动角度、分辨率、响应速度和扭矩。
转动角度指的是舵机可以实现的最大转动角度,通常在0-180度之间。
分辨率指的是舵机可以实现的最小调整角度,通常可以达到1度以下。
响应速度指的是舵机从接受到控制信号后开始转动的时间,一般可以在几毫秒内完成。
扭矩指的是舵机能够承受的最大力矩,通常以kg∙cm为单位。
章节三:51单片机在舵机控制中的应用51单片机是一种小型微控制器,具有丰富的外设资源和强大的数据处理能力,广泛应用于嵌入式系统和自动控制领域。
在舵机控制中,51单片机可以通过产生PWM(脉宽调制)信号来实现对舵机的角度控制。
通过改变PWM信号的高电平时间,可以控制舵机转动到不同的角度。
在51单片机的程序设计中,首先需要进行舵机控制电路的硬件设计。
控制电路包括将单片机输出引脚与舵机相连的电路以及电源电路。
接下来,在软件设计中,需要编写相应的代码实现舵机控制功能。
代码主要包括PWM信号的产生、舵机角度控制算法的实现和与外设的交互等部分。
章节四:舵机控制程序的优化与应用拓展在舵机控制程序的优化方面,可以通过改进PWM信号的生成方法来提高程序的效率和精确度。
C51代码(PWM)

1.#include < reg51.h >2.#include < intrins.h >3.4.sbit K1 =P1^4 ; //增加键5.sbit K2 =P1^5 ; //减少键6.sbit P00 =P0^1;7.sbit BEEP =P3^7 ; //蜂鸣器8.unsigned char PWM=0xe7; //赋初值9.10.void Beep();11.void delayms(unsigned char ms);12.void delay(unsigned char t);13.14./*********************************************************/15.void main()16.{17.18. P1=0xff;19. TMOD=0x21 ;20. TH0=0xff ; //50us延时常数21. TL0=0xce ; //频率调节22.23. TH1=PWM ; //脉宽调节24. TL1=0 ;25.26. EA=1;27. ET0=1;28. ET1=1;29.30. TR0=1 ;31.32. while(1)33. {34. do{35. if(PWM!=0xff)36. {PWM++ ;delayms(10);}37. else Beep() ;38. }39. while(K1==0);40.41. do{42. if(PWM!=0xce)43. {PWM-- ;delayms(10);}44. else Beep() ;45. }46. while(K2==0);47. }48.}49.50.void timer0() interrupt 151.{52. TR1=0 ;53. TH0=0xff ;54. TL0=0xce ;55. TH1=PWM ;56. TR1=1 ;57. P00=0 ; //启动输出58.}59.60.61.void timer1() interrupt 362.{63. TR1=0 ;64. P00=1 ; //完毕输出65.}66.67./*********************************************************/68.//蜂鸣器子程序69./*********************************************************/70.71.void Beep()72. {73. unsigned char i ;74. for (i=0 ;i<100 ;i++)75. {76. delay(100) ;77. BEEP=!BEEP ; //Beep取反78. }79. BEEP=1 ; //关闭蜂鸣器80. delayms(100);81. }82.83./*********************************************************/84.// 延时子程序85./*********************************************************/86.void delay(unsigned char t)87.{88. while(t--) ;89.}90.91./*********************************************************/92.// 延时子程序93./*********************************************************/94.void delayms(unsigned char ms)95.96.{97. unsigned char i ;98. while(ms--)99. {100. for(i = 0 ; i < 120 ; i++) ;101. }102.}103.104./*********************************************************/ 105.#include < reg51.h >106.#include < intrins.h >107.108.sbit K1 =P1^4 ; //增加键109.sbit K2 =P1^5 ; //减少键110.sbit P00 =P0^1;111.sbit BEEP =P3^7 ; //蜂鸣器112.unsigned char PWM=0xe7; //赋初值113.114.void Beep();115.void delayms(unsigned char ms);116.void delay(unsigned char t);117.118./*********************************************************/ 119.void main()120.{121.122. P1=0xff;123. TMOD=0x21 ;124. TH0=0xff ; //50us延时常数125. TL0=0xce ; //频率调节126.127. TH1=PWM ; //脉宽调节128. TL1=0 ;129.130. EA=1;131. ET0=1;132. ET1=1;134. TR0=1 ;135.136. while(1)137. {138. do{139. if(PWM!=0xff)140. {PWM++ ;delayms(10);} 141. else Beep() ;142. }143. while(K1==0);144.145. do{146. if(PWM!=0xce)147. {PWM-- ;delayms(10);} 148. else Beep() ;149. }150. while(K2==0);151. }152.}153.154.void timer0() interrupt 1156. TR1=0 ;157. TH0=0xff ;158. TL0=0xce ;159. TH1=PWM ;160. TR1=1 ;161. P00=0 ; //启动输出162.}163.164.165.void timer1() interrupt 3166.{167. TR1=0 ;168. P00=1 ; //完毕输出169.}170.171./*********************************************************/ 172.//蜂鸣器子程序173./*********************************************************/ 174.175.void Beep()176. {177. unsigned char i ;178. for (i=0 ;i<100 ;i++)179. {180. delay(100) ;181. BEEP=!BEEP ; //Beep取反182. }183. BEEP=1 ; //关闭蜂鸣器184. delayms(100);185. }186.187./*********************************************************/ 188.// 延时子程序189./*********************************************************/ 190.void delay(unsigned char t)191.{192. while(t--) ;193.}194.195./*********************************************************/ 196.// 延时子程序197./*********************************************************/ 198.void delayms(unsigned char ms)199.200.{201. unsigned char i ;202. while(ms--)203. {204. for(i = 0 ; i < 120 ; i++) ;205. }206.}207.208./*********************************************************/ 209.#include < reg51.h >210.#include < intrins.h >211.212.sbit K1 =P1^4 ; //增加键213.sbit K2 =P1^5 ; //减少键214.sbit P00 =P0^1;215.sbit BEEP =P3^7 ; //蜂鸣器216.unsigned char PWM=0xe7; //赋初值217.218.void Beep();219.void delayms(unsigned char ms);220.void delay(unsigned char t);221.222./*********************************************************/ 223.void main()224.{225.226. P1=0xff;227. TMOD=0x21 ;228. TH0=0xff ; //50us延时常数229. TL0=0xce ; //频率调节230.231. TH1=PWM ; //脉宽调节232. TL1=0 ;233.234. EA=1;235. ET0=1;236. ET1=1;237.238. TR0=1 ;239.240. while(1)241. {242. do{243. if(PWM!=0xff)244. {PWM++ ;delayms(10);} 245. else Beep() ;246. }247. while(K1==0);248.249. do{250. if(PWM!=0xce)251. {PWM-- ;delayms(10);} 252. else Beep() ;253. }254. while(K2==0);255. }256.}257.258.void timer0() interrupt 1259.{260. TR1=0 ;261. TH0=0xff ;262. TL0=0xce ;263. TH1=PWM ;264. TR1=1 ;265. P00=0 ; //启动输出266.}267.268.269.void timer1() interrupt 3270.{271. TR1=0 ;272. P00=1 ; //完毕输出273.}274.275./*********************************************************/ 276.//蜂鸣器子程序277./*********************************************************/ 278.279.void Beep()280. {281. unsigned char i ;282. for (i=0 ;i<100 ;i++)283. {284. delay(100) ;285. BEEP=!BEEP ; //Beep取反286. }287. BEEP=1 ; //关闭蜂鸣器288. delayms(100);289. }290.291./*********************************************************/ 292.// 延时子程序293./*********************************************************/ 294.void delay(unsigned char t)295.{296. while(t--) ;297.}298.299./*********************************************************/ 300.// 延时子程序301./*********************************************************/ 302.void delayms(unsigned char ms)303.304.{305. unsigned char i ;306. while(ms--)307. {308. for(i = 0 ; i < 120 ; i++) ;309. }310.}311.312./*********************************************************/ 313.#include < reg51.h >314.#include < intrins.h >315.316.sbit K1 =P1^4 ; //增加键317.sbit K2 =P1^5 ; //减少键318.sbit P00 =P0^1;319.sbit BEEP =P3^7 ; //蜂鸣器320.unsigned char PWM=0xe7; //赋初值321.322.void Beep();323.void delayms(unsigned char ms);324.void delay(unsigned char t);325.326./*********************************************************/ 327.void main()328.{329.330. P1=0xff;331. TMOD=0x21 ;332. TH0=0xff ; //50us延时常数333. TL0=0xce ; //频率调节334.335. TH1=PWM ; //脉宽调节336. TL1=0 ;337.338. EA=1;339. ET0=1;340. ET1=1;341.342. TR0=1 ;343.344. while(1)345. {346. do{347. if(PWM!=0xff)348. {PWM++ ;delayms(10);}349. else Beep() ;350. }351. while(K1==0);352.354. if(PWM!=0xce)355. {PWM-- ;delayms(10);} 356. else Beep() ;357. }358. while(K2==0);359. }360.}361.362.void timer0() interrupt 1 363.{364. TR1=0 ;365. TH0=0xff ;366. TL0=0xce ;367. TH1=PWM ;368. TR1=1 ;369. P00=0 ; //启动输出370.}371.372.373.void timer1() interrupt 3 374.{376. P00=1 ; //完毕输出377.}378.379./*********************************************************/ 380.//蜂鸣器子程序381./*********************************************************/ 382.383.void Beep()384. {385. unsigned char i ;386. for (i=0 ;i<100 ;i++)387. {388. delay(100) ;389. BEEP=!BEEP ; //Beep取反390. }391. BEEP=1 ; //关闭蜂鸣器392. delayms(100);393. }394.395./*********************************************************/ 396.// 延时子程序397./*********************************************************/ 398.void delay(unsigned char t)399.{400. while(t--) ;401.}402.403./*********************************************************/ 404.// 延时子程序405./*********************************************************/ 406.void delayms(unsigned char ms)407.408.{409. unsigned char i ;410. while(ms--)411. {412. for(i = 0 ; i < 120 ; i++) ;413. }414.}415.416./*********************************************************/ 417.#include < reg51.h >418.#include < intrins.h >419.420.sbit K1 =P1^4 ; //增加键421.sbit K2 =P1^5 ; //减少键422.sbit P00 =P0^1;423.sbit BEEP =P3^7 ; //蜂鸣器424.unsigned char PWM=0xe7; //赋初值425.426.void Beep();427.void delayms(unsigned char ms);428.void delay(unsigned char t);429.430./*********************************************************/ 431.void main()432.{433.434. P1=0xff;435. TMOD=0x21 ;436. TH0=0xff ; //50us延时常数437. TL0=0xce ; //频率调节438.439. TH1=PWM ; //脉宽调节440. TL1=0 ;441.442. EA=1;443. ET0=1;444. ET1=1;445.446. TR0=1 ;447.448. while(1)449. {450. do{451. if(PWM!=0xff)452. {PWM++ ;delayms(10);} 453. else Beep() ;454. }455. while(K1==0);456.457. do{458. if(PWM!=0xce)459. {PWM-- ;delayms(10);} 460. else Beep() ;461. }462. while(K2==0);463. }464.}465.466.void timer0() interrupt 1467.{468. TR1=0 ;469. TH0=0xff ;470. TL0=0xce ;471. TH1=PWM ;472. TR1=1 ;473. P00=0 ; //启动输出474.}475.476.477.void timer1() interrupt 3478.{479. TR1=0 ;480. P00=1 ; //完毕输出481.}482.483./*********************************************************/ 484.//蜂鸣器子程序486.487.void Beep()488. {489. unsigned char i ;490. for (i=0 ;i<100 ;i++)491. {492. delay(100) ;493. BEEP=!BEEP ; //Beep取反494. }495. BEEP=1 ; //关闭蜂鸣器496. delayms(100);497. }498.499./*********************************************************/ 500.// 延时子程序501./*********************************************************/ 502.void delay(unsigned char t)503.{504. while(t--) ;505.}506.508.// 延时子程序509./*********************************************************/ 510.void delayms(unsigned char ms)511.512.{513. unsigned char i ;514. while(ms--)515. {516. for(i = 0 ; i < 120 ; i++) ;517. }518.}519.520./*********************************************************/ 521.#include < reg51.h >522.#include < intrins.h >523.524.sbit K1 =P1^4 ; //增加键525.sbit K2 =P1^5 ; //减少键526.sbit P00 =P0^1;527.sbit BEEP =P3^7 ; //蜂鸣器528.unsigned char PWM=0xe7; //赋初值530.void Beep();531.void delayms(unsigned char ms);532.void delay(unsigned char t);533.534./*********************************************************/ 535.void main()536.{537.538. P1=0xff;539. TMOD=0x21 ;540. TH0=0xff ; //50us延时常数541. TL0=0xce ; //频率调节542.543. TH1=PWM ; //脉宽调节544. TL1=0 ;545.546. EA=1;547. ET0=1;548. ET1=1;549.550. TR0=1 ;552. while(1)553. {554. do{555. if(PWM!=0xff)556. {PWM++ ;delayms(10);} 557. else Beep() ;558. }559. while(K1==0);560.561. do{562. if(PWM!=0xce)563. {PWM-- ;delayms(10);} 564. else Beep() ;565. }566. while(K2==0);567. }568.}569.570.void timer0() interrupt 1571.{572. TR1=0 ;573. TH0=0xff ;574. TL0=0xce ;575. TH1=PWM ;576. TR1=1 ;577. P00=0 ; //启动输出578.}579.580.581.void timer1() interrupt 3582.{583. TR1=0 ;584. P00=1 ; //完毕输出585.}586.587./*********************************************************/ 588.//蜂鸣器子程序589./*********************************************************/ 590.591.void Beep()592. {593. unsigned char i ;594. for (i=0 ;i<100 ;i++)595. {596. delay(100) ;597. BEEP=!BEEP ; //Beep取反598. }599. BEEP=1 ; //关闭蜂鸣器600. delayms(100);601. }602.603./*********************************************************/ 604.// 延时子程序605./*********************************************************/ 606.void delay(unsigned char t)607.{608. while(t--) ;609.}610.611./*********************************************************/ 612.// 延时子程序613./*********************************************************/ 614.void delayms(unsigned char ms)615.616.{617. unsigned char i ;618. while(ms--)619. {620. for(i = 0 ; i < 120 ; i++) ;621. }622.}623.624./*********************************************************/。
舵机的控制程序51单片机写的

舵机的控制程序51单片机写的//请根据自己马达的控制来改变程序#include<reg52.h>#include<math.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar Buffer =0; //从串口接收的数据uint URTAReceivedCount=0,n=1;uchar data Tempdatatable[5],CommandDatatable[5];//数据包uchar serVal[2];//uint pwm[]={1120,1190,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计数bit key_stime_ok;void Delay_1ms(uint i)//1ms延时{uchar x,j;for(j=0;jfor(x=0;x<=148;x++);}void Send_Data(uchar type,uchar cmd,uchar dat){uchar data Buffer[5];//构建数据包uchar *p;uint Send_Count=0;p = Buffer;Buffer[0]=0XFF;Buffer[1]=type;Buffer[2]=cmd;Buffer[3]=dat;Buffer[4]=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;}}}void Com_Int(void) interrupt 4{uchar temp;ES=0; //关串口中断RI=0; //软件清除接收中断temp=SBUF;if(temp==0XFF && URTAReceivedCount<3) {Tempdatatable[0]==0XFF; //包头URTAReceivedCount++;}else{Tempdatatable[n]=temp;n++;if(URTAReceivedCount==0&&n==2)n=1;}if(URTAReceivedCount==2)//包尾{Tempdatatable[0]=0XFF;Tempdatatable[4]=0XFF;n=1;URTAReceivedCount=0; //组包完毕temp=" ";//Send_Data(Tempdatatable[1],Tempdatatable[2],Tempdatatable[3 ]); //发送组成的数据包回去}CommandDatatable[0]=Tempdatatable[0];CommandDatatable[1]=Tempdatatable[1];CommandDatatable[2]=Tempdatatable[2];CommandDatatable[3]=Tempdatatable[3];CommandDatatable[4]=Tempdatatable[4];ES=1;//开串口中断}void Com_Init(void){TMOD = 0x21;PCON = 0x00;SCON = 0x50;TH1 = 0xFd; //设置波特率 9600TL1 = 0xFd;TR1 = 1; //启动定时器1ES = 1; //开串口中断EA = 1; //开总中断IT0=0;EX0=1;}void main(){Delay_1ms(200);Com_Init();//串口初始化Timer0Init();//舵机PWM中断初始化while(1){if(CommandDatatable[0]==0XFF && CommandDatatable[4]==0XFF){switch (CommandDatatable[1]) //根据键值不同,执行不同的内容{case 0X00: //类型位0X00,表明是控制数据包,进入控制数据caseswitch(CommandDatatable[2]) //根据数据位的值来进行选择执行不同的动作{case 0X00:Moto_Stop();break;case 0X01:Moto_Forward();break;case 0X02:Moto_Backward();break;case 0X03:Moto_TurnLeft();break;case 0X04:Moto_TurnRight();break;case 0X05:Moto_ForLeft();break;case 0X06:Moto_ForRight();break;case 0X07:Moto_BackLeft();break;case 0X08:Moto_BackRight();break;default : break;}break;default : break;}}}}。
51控制舵机程序

51控制舵机程序章节一:引言(约200字)舵机是一种广泛应用于机器人、航空模型、无人机等控制系统中的关键部件。
其通过控制电流使舵盘旋转,从而实现控制机械臂、舵面等部件的运动。
51单片机作为一种常用的微控制器,具备处理速度快、成本低、易编程等优点,被广泛应用于舵机控制。
本文旨在介绍利用51单片机控制舵机的主要方法和步骤,并通过实验验证舵机控制效果。
章节二:51单片机舵机控制原理(约300字)51单片机通过PWM(脉冲宽度调制)技术来控制舵机。
PWM波形的占空比决定了舵机的位置。
当占空比为0%时,舵机处于最左转位置;当占空比为100%时,舵机处于最右转位置;当占空比为50%时,舵机处于中间位置。
通过改变占空比大小可以控制舵机的角度。
章节三:51单片机舵机控制程序设计(约300字)首先,需要通过51单片机的GPIO口与舵机连接,将舵机的控制线连接到51单片机的PWM输出口。
接下来,在主程序中初始化PWM相关参数,例如PWM的频率、占空比等。
然后,在主循环中,通过改变PWM占空比的值,实现对舵机位置的控制。
可以通过控制PWM值的增减来控制舵机的角度。
章节四:实验验证与结果分析(约200字)实验中,我们使用51单片机和舵机进行舵机控制实验。
通过改变PWM占空比大小,我们可以观察到舵机位置的变化。
实验结果显示,随着PWM占空比的增加,舵机的角度逐渐增加,反之亦然。
通过实验验证,说明了51单片机可以有效地控制舵机的运动。
综上所述,本文介绍了51单片机控制舵机的原理、程序设计步骤,并通过实验证明了其控制效果。
通过本文的研究,可以为舵机控制的相关研究提供参考和借鉴。
章节一:引言(约200字)舵机是一种广泛应用于机器人、航空模型、无人机等控制系统中的关键部件。
其通过控制电流使舵盘旋转,从而实现控制机械臂、舵面等部件的运动。
51单片机作为一种常用的微控制器,具备处理速度快、成本低、易编程等优点,被广泛应用于舵机控制。
PWM信号控制KeilC51演示程序

/*----------------------------------------------------------------零耗时低频宽脉冲软PWM信号控制Keil C51演示程序C51文件PwmDemo.cHotPower@ 作于2004.11.17与大雁塔村队部在uV3中对PWM信号进行"实时仿真"效果逼真。
-----------------------------------------------------------------*/#include//#include#include/*------------------------------------------------A T89S5X SFR定义(REGX52.h中未定义)--------------------------------------------------*/sfr AUXR = 0x8e;sfr WDTRST = 0xa6;sfr16 TIMEER2 = 0xcc;sfr16 RCAP2 = 0xca;/*-----------------------------------------------PWM管脚定义------------------------------------------------*/sbit PWM = P1^0;//可以为任意IO管脚typedef struct Systemstruct{//系统数据结构unsigned int PwmCount;//700~2300uSunsigned int RamTest;//内部ram自检变量/*--------------------------------------------------------------------注意将STARTUP.A51中的IDA TALEN改写为0,RamTest才能完成MCU掉电自检。
基于51单片机控制多路舵机的方法

基于51单片机控制多路舵机的方法作者:昝鹭鸶张晗冀向阳来源:《科学与财富》2017年第25期摘要:在现在的时代下,机电一体化是发展的必然趋势。
现在很多的项目已经不再是纯机械结构了,要求要有电控。
加上电控的设备可以节省人力,让机器自己运行起来。
就连现在简单的加工机床都要求要有一定的自动化。
随着这科技的发展,电控的方式越来越多。
在做机电一体化设备的时候,谈起电控部分,首先进入眼帘的就是使用单片机配上传感器做成一个开环或是闭环控制系统。
单片机在传感器的感知下,驱动着动力源元件运转,进而带动整个机器运动,完成预期的动作。
这里面的动力源元件一般有步进电机,伺服电机,舵机,直流减速电机等,舵机是最常用的元件之一。
对于一个复杂的工程项目,例如仿生机械臂,仿生机器人等项目一般需要多个舵机。
那么对于主控板是51板的电控系统,为了节省资源,常常用一片51单片机控制多个舵机运动。
关键词:51单片机;多路舵机;正文:对于用一片51单片机来控制多路舵机运动,往往是一个让程序员头疼的问提。
因为舵机可以转动一个相对精准的角度,要是想让舵机转动的非常灵敏,那么就会带来一系列的问题、用51单片机控制舵机转动的原理是利用定时器中断产生一个周期为20ms的PWM波。
我们通过控制这个PWM波中高电平所占的时间长短使舵机转动相应的角度。
理论上讲,允许高电平时间变化的越精细就会使舵机转动的越精准。
一般想到的方法就是让定时器产生中断的时间越短,通过在定时器中断中产生PWM波来驱动舵机转动。
这样的想法在一些简单的工程中应用时可以的。
这里面提到的简单的工程是指舵机的数目少,一般为一路或两路舵机。
但是这样也不能使舵机转动的角度非常灵敏。
倘若使用这个想法使舵机转动的非常精准,就要使定时器的定时非常短,也就是说51单片机会频繁的响应定时器中断,这样会带来很多的问题。
问题一就是倘若这个工程要求要有串口通讯,那么平凡的响应定时器中断会影响在串口通信中所设定的波特率,(这个与pwm波与波特率所用的定时器中断的优先级有关,如果pwm波采用定时器0中断,波特率采用定时器1中断,因为在51单片机的中断源中,定时器0中断比定时器1中断的优先级高,当51单片机频繁响应定时器0中断时,会影响波特率的值,这样串口通讯就会产生一些错误,如在串口通讯中接收到的数据和发送的数据不一致,那么就会导致串口通讯失去作用。
51单片机分时控制8路舵机程序

{
pwm5=1;
Timer0(pwm[4]);
} break;
case 10:
{
pwm5=0;
Timer0(2500-pwm[4]);
} break;
case 11:
{
pwm6=1;
Timer0(pwm[5]);
} break;
case 12:
{
pwm6=0;
Timer0(2500-pwm[5]);
{
pwm3=1;
Timer0(pwm[2]);
} break;
case 6:
{
pwm3=0eak;
case 7:
{
pwm4=1;
Timer0(pwm[3]);
} break;
case 8:
{
pwm4=0;
Timer0(2500-pwm[3]);
} break;
uint16 j;
for(i=0;i<1000;i++)
for(j=0;j<time;j++);
}
void Timer_init()
{
EA=1; //开总中断
AUXR|=0xC0; //T0,T1工作在1T
TMOD|= 0x11; //T0工作在方式1,16位
ET0 = 1; //开定时器0中断
}
void Timer0(uint32 us)
sbit pwm6=P0^5;
sbit pwm7=P0^6;
sbit pwm8=P0^7;
void main()
{
P0M1=0;
P0M0=0XFF;
Timer_init();
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、 基本原理介绍
二、
演示机构采用的是舵机,每个需要一路PWM 波
和两路电源输入。
电源输入标准为5V 1-8A ,采用
带输入和输出保护的50w 开关电源供电;PWM 波为
50Hz ,正脉冲时间为0.5-2.5ms ,对应-90°至90°
(实际使用中为了保护机械,为0.7-2.3ms ,舵机
旋转范围为-70°至70°)。
由于系统对于输出的频率有5
Hz 的限制,因此使用软件延迟来实现最多八路的
的PWM 波输出。
PWM 波由MCU 通过软件延时产生,
算法概述如下(流程图见附件):
1. A 路输出
2.5ms 脉冲(输出正脉冲,不足
时间由低电平 补至2.5ms ),此时其他五
路无输出,相当于输出2.5ms 低电平; 2. B 路输出2.5ms 脉冲(同A 路,不足时间由低电平补齐),此时包括A 路的其他五路无输出,相当于输出2.5ms 低电平;
3. 同理,输出C,D,E,F 路
4. 此时,1-3步总时间为2.5*6=15ms ,其中每路由一个小于2.5ms 的正脉冲和低电平时间组成。
由于输出周期为20ms ,故应再输出20ms-15ms=5ms 低电平时间,使得各路频率为50Hz 。
重复1-3步,得到输出波形如下图:(仅以4路为例,使用Proteus 仿真示波器,图
2.2.2)
可以看到,此时各路输出均为50Hz ,正脉冲时间为
0.5-2.5ms
图 2.2.1 舵机及其控制原理
图2.2.2 Proteus仿真
此算法在50Hz(20ms)频率的限制下,最多可输出8路PWM波形(8*2.5ms=20ms)
三、实际程序
程序如下:
#include <stdio.h>
#include <REG52.h>
#define uchar unsigned char
#define uint unsigned int
sbit Out1=P2^0;
sbit Out2=P2^1;
sbit Out3=P2^2;
sbit Out4=P2^3;
sbit Out5=P2^4;
void PWM(uint a, uint b,uint c, uint d,uint e) {
uchar A,B,C,D,E;
uint M=984;
A=250-a;
B=250-b;
C=250-c;
D=250-d;
E=250-e;
do { Out1 = 1; } while(a--);
do { Out1 = 0; } while(A--);
do { Out2 = 1; } while(b--);
do { Out2 = 0; } while(B--);
do { Out3 = 1; } while(c--);
do { Out3 = 0; } while(C--);
do { Out4 = 1; } while(d--);
do { Out4 = 0; } while(D--);
do { Out5 = 1; } while(e--);
do { Out5 = 0; } while(E--);
do{ }while(M--);
}
main()
uchar a,b,c,d,e;
uint m;
a=170;
b=149;
c=d=e=149;
SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1 TMOD = 0x20; //定时器工作方式2
PCON = 0x80;
//TH1 = 0xFD; //baud*2 /* reload value 19200、数据位8、停止位1。
效验位无 (11.0592)
TH1 = 0xF3; // //baud*2 /* 波特率4800、数据位8、停止位1。
效验
位无 (12M)
TL1 = 0xF3;
TR1 = 1;
ES = 1; //开串口中断
EA = 1; // 开总中断
while(1)
{
if(RI)
{
RI=0;
m=SBUF-48;
if(m==1)
{
if(a<=120) a=a+3; else a=a+1;
}
if(m==2)
{
if(a>=180)a=a-3; else a=a-1;
}
if(m==3) b=b+1;
if(m==4) b=b-1;
if(m==5) c=c+1;
if(m==6) c=c-1;
if(m==7) d=d+1;
if(m==8) d=d-1;
if(m==9) e=e+1;
if(m==0) e=e-1;
if(a<=69) a=69;
if(a>=229) a=228;
if(b<=69) b=69;
if(b>=229) b=228;
if(c<=69) b=69;
if(c>=229) b=228;
if(d<=69) b=69;
if(d>=229) b=228;
if(e<=69) b=69; if(e>=229) b=228;
}
else
{
PWM(a,b,c,d,e); }
}
}。