① 改一下单片机控制PWM直流电机的程序
单片机控制PWM直流电机的程序,具体如下:
PWM控制直流电机实现上来说应该不难,最主要是要求:比如加速度,需要多块达到设定速度;
一般来讲有“开环的查表法”和“闭环的采集实时速度法”;
“开环查表”:前提是知道要达到的速度是哪些,然后去增加(或减少)PWM的占空比来看速度是否和设定的一致,然后将此时的占空比放到表格中,下次需要用时,直接根据设定速度查表格就行;这种控制方法适合于“负载”不变的情况,相对简单;
“闭环速度采集”:在硬件电路上要有速度采集系统(霍尔元件),根据反馈的速度大小来调节PWM的占空比,这种方法比较精确,适用于不同的“负载”,在控制速度的过程中要小心“超调”,也就是速度加的太快或者太慢(PWM占空比调节太快),可以通过试验来确定调节的快慢或者引入PID算法;
控制电机:要了解可控硅的使用。
例子:
51单片机直流电机的PWM速度控制程序的代码如下:
/* =======直流电机的PWM速度控制程序======== */
/* 晶振采用11.0592M,产生的PWM的频率约为91Hz */
#include<reg51.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
sbit en1=P2^0; /* L298的Enable A */
sbit en2=P2^1; /* L298的Enable B */
sbit s1=P2^2; /* L298的Input 1 */
sbit s2=P2^3; /* L298的Input 2 */
sbit s3=P2^4; /* L298的Input 3 */
sbit s4=P2^5; /* L298的Input 4 */
uchar t=0; /* 中断计数器 */
uchar m1=0; /* 电机1速度值 */
uchar m2=0; /* 电机2速度值 */
uchar tmp1,tmp2; /* 电机当前速度值 */
/* 电机控制函数 index-电机号(1,2); speed-电机速度(-100—100) */
void motor(uchar index, char speed)
{
if(speed>=-100 && speed<=100)
{
if(index==1) /* 电机1的处理 */
{
m1=abs(speed); /* 取速度的绝对值 */
if(speed<0) /* 速度值为负则反转 */
{
s1=0;
s2=1;
}
else /* 不为负数则正转 */
{
s1=1;
s2=0;
}
}
if(index==2) /* 电机2的处理 */
{
m2=abs(speed); /* 电机2的速度控制 */
if(speed<0) /* 电机2的方向控制 */
{
s3=0;
s4=1;
}
else
{
s3=1;
s4=0;
}
}
}
}
void delay(uint j) /* 简易延时函数 */
{
for(j;j>0;j--);
}
void main()
{
char i;
TMOD=0x02; /* 设定T0的工作模式为2 */
TH0=0x9B; /* 装入定时器的初值 */
TL0=0x9B;
EA=1; /* 开中断 */
ET0=1; /* 定时器0允许中断 */
TR0=1; /* 启动定时器0 */
while(1) /* 电机实际控制演示 */
{
for(i=0;i<=100;i++) /* 正转加速 */
{
motor(1,i);
motor(2,i);
delay(5000);
}
for(i=100;i>0;i--) /* 正转减速 */
{
motor(1,i);
motor(2,i);
delay(5000);
}
for(i=0;i<=100;i++) /* 反转加速 */
{
motor(1,-i);
motor(2,-i);
delay(5000);
}
for(i=100;i>0;i--) /* 反转减速 */
{
motor(1,-i);
motor(2,-i);
delay(5000);
}
}
}
void timer0() interrupt 1 /* T0中断服务程序 */
{
if(t==0) /* 1个PWM周期完成后才会接受新数值 */
{
tmp1=m1;
tmp2=m2;
}
if(t<tmp1) en1=1; else en1=0; /* 产生电机1的PWM信号 */
if(t<tmp2) en2=1; else en2=0; /* 产生电机2的PWM信号 */
t++;
if(t>=100) t=0; /* 1个PWM信号由100次中断产生 */
}
② 51单片机怎么驱动直流电机c语言
51单片机驱动直流电机程序(用的是l298n芯片):
#include<reg51.h>
#include<math.h>
#defineuintunsignedint
#defineucharunsignedchar
#defineN100
sbits1=P1^0;//电机驱动口
sbits2=P1^1;//电机驱动口
sbits3=P1^2;//电机驱动口
sbits4=P1^3;//电机驱动口
sbiten1=P1^4;//电机使能端
sbiten2=P1^5;//电机使能端
sbitLSEN=P2^0;//光电对管最左
sbitLSEN1=P2^1;//光电对管左1
sbitLSEN2=P2^2;//光电对管左2
sbitRSEN1=P2^3;//光电对管右1
sbitRSEN2=P2^4;//光电对管右2
sbitRSEN=P2^5;//光电对管最右
uintpwm1=0,pwm2=0,t=0;
voiddelay(uintxms)
{
uinta;
while(--xms)
{
for(a=123;a>0;a--);
}
}
voidmotor(ucharspeed1,ucharspeed2)
{
if(speed1>=-100&&speed1<=100)
{
pwm1=abs(speed1);
if(speed1>0)
{
s1=1;
s2=0;
}
if(speed1==0)
{
s1=1;
s2=1;
}
if(speed1<0)
{
s1=0;
s2=1;
}
}
if(speed2>=-100&&speed2<=100)
{
pwm2=abs(speed2);
if(speed2>0)
{
s3=1;
s4=0;
}
if(speed2==0)
{
s3=1;
s4=1;
}
if(speed2<0)
{
s3=0;
s4=1;
}
}
}
voidgo_forward(uintspeed)
{
s1=1;
s2=0;
s3=1;
s4=0;
pwm1=speed;
pwm2=speed;
}
voidgo_back(uintspeed)
{
s1=0;
s2=1;
s3=0;
s4=1;
pwm1=speed;
pwm2=speed;
}
voidstop()
{
s1=1;
s2=1;
s3=1;
s4=1;
pwm1=0;
pwm2=0;
}
voidturn_right(uintP1,uintP2)//右转函数
{
s1=1;
s2=0;
s3=0;
s4=1;
pwm1=P1;
pwm2=P2;
}
voidturn_left(uintP1,uintP2)//左转函数
{
s1=0;
s2=1;
s3=1;
s4=0;
pwm1=P1;
pwm2=P2;
}
voidtracking()
{
if((LSEN1==0)&&(LSEN2==0)&&(RSEN1==0)&&(RSEN2==0))//没有检测到
{
go_forward(100);
}
if((LSEN1==1)&&(LSEN2==0)&&(RSEN1==0)&&(RSEN2==0))//左一检测到
{
turn_left(40,80);//左转右轮》左轮
delay(N);
}
if((LSEN1==0)&&(LSEN2==1)&&(RSEN1==0)&&(RSEN2==0))//左二检测到
{
turn_left(40,60);//左转右轮》左轮
delay(N);
}
if((LSEN1==0)&&(LSEN2==0)&&(RSEN1==1)&&(RSEN2==0))//右一检测到
{
turn_right(60,4);//右转左轮》右轮
delay(N);
}
if((LSEN1==0)&&(LSEN2==0)&&(RSEN1==0)&&(RSEN2==1))//右二检测到
{
turn_right(80,40);//右转左轮》右轮
delay(N);
}
if((LSEN1==1)&&(LSEN2==1))
{
turn_left(0,100);
delay(1000);
}
if((RSEN1==1)&&(RSEN2==1))
{
turn_right(100,0);
delay(1000);
}
}
voidavoidance()
{
}
voidinit()
{
TMOD=0x02;//timer0同时配置为模式2,8自动重装计数模式
TH0=156;//定时器初值设置100us中断
TL0=156;
ET0=1;
EA=1;
TR0=1;//开启总中断
}
voidmain()
{
init();
while(1)
{
tracking();
}
}
voidtimer0()interrupt1//电机驱动提供PWM信号
{
if(t<pwm1)
en1=1;
else
en1=0;
if(t<pwm2)
en2=1;
else
en2=0;
t++;
if(t>100)
t=0;
}
(2)51单片机直流电机调速程序扩展阅读
L298N是一种双H桥电机驱动芯片,其中每个H桥可以提供2A的电流,功率部分的供电电压范围是2.5-48v,逻辑部分5v供电,接受5vTTL电平。一般情况下,功率部分的电压应大于6V否则芯片可能不能正常工作。
③ 51单片机实现pwm对电机调速
可以用一个定时器实现,也可以用两个定时器实现
一个定时器实现办法,如定时器定时50US中断一次,中断100次是5ms,即PWM的周期
每次中断,变量a加1,并且a与另一变量b比较,如果a<b,让某一管脚输出高电平,如果a>=b,则让其输出低电平,a等于100时清0,这样占空比是b/100,改变b的值,就可以改变占空比
缺点定时器定时时间不能太短,例如10us中断程序根本执行不完,若占空比调节精度要求较高,如要求百分之一,则a需大于100,这样PWM波的周期就比较大,频率比较低
两个定时器,如一个定时器0定时100us,另外一个定时器1定时小于100us,如b
us
定时器0中断时输出高电平,并打开定时器1,定时器1负责置低电平
这样,就可以产生周期100us,占空比是b/100的方波
频率可以比用一个定时器高一些
④ 51单片机控制直流电机。(c语言控制)
有3种方案:
第一种,通过PWM脉宽调制输出方法控制转速,控制占空比的大小可以实现调速!
第二种,通过AD转换的方法控制直流电机的电压
第三种,用xtr115程控电流源来控制直流电机(类似第二种方法)
如果以上的驱动能力不够的话再加上一个电压跟随器!
程序方面就是一个寄存器的配置问题了,你查一下单片机的技术手册上面都有介绍的,祝你成功
⑤ 51单片机控制两路直流电机转速的c程序技巧
既然是技巧的话那就不提供详细的代码了,首先要看你这个小车是几轮几驱动的,首先假设你只用一个L298n驱动板的话,那么再假设只含左右两个轮,只对左右两个轮进行控制的话,那么就简单了,首先你要知道L298N驱动板怎么用,不同的驱动板功能都不一定相同,不过控制引脚一般来说都是4根,可以控制两个直流电机的正反转,同时还有两个PWM接口,可以控制两个电机的转速。
假设4个控制引脚分为A1、A2和B1、B2,A1、A2控制第一个直流电机,B1、B2控制第二个直流电机,当A1和A2接不同方向的电流后直流电机会正转或反转,同理B1和B2也是一样。PWM是通过控制占有率来控制电机速度的,即控制高电平和低电平的时间的,不同,这样在规定时间内,如果高电平的时间占有比例越高则电机转速越快,输出功率越高。
知道以上内容了那么之后的内容就更容易理解了
前进:两个直流电机朝正方向同时转动即可
后退:两个直流电机朝反方向同时转动即可
原地左转:类似原地打转,只需让两个电机一个正转一个反转即可,即左转为左边电机反转,右边电机正转
原地右转:与原地左转相反即可
固定轮转:固定左边令右侧轮前进即可实现固定轮转向的目的,例如左转的话令左边电机停止,右侧电机正向转动即可,向右转的话与左转相反。
至于keil程序,这个要根据具体的硬件来写,别人的无法通用,不过这些都不难,只要原理弄懂了,稍微花一点儿时间还是能很容易写出来的,先从控制电机的转向开始。别人的程序的话可能会越看越难理解,还是自己动手比较好,先不考虑调速的情况下完成了之后再去看看有关PWM调速的内容。
⑥ 51单片机直流电机调速
第一:你这个不是电机调速的,用外部中断是测速的呀。
下面是我写的.PID部分的代码就不给了,想加的话,自己找可以了
#include <AT89X52.H>
#include "common.h"
#define _WHEEL_C_
#define Left_moto_pwm P1_5
#define Right_moto_pwm P1_4
#define Left_moto_go {IN1=0,IN2=1;}
#define Left_moto_back {IN1=1,IN2=0;}
#define Right_moto_go {IN3=1,IN4=0;}
#define Right_moto_back {IN3=0,IN4=1;}
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^2;
sbit IN4=P1^3;
unsigned char pwm_val_left=0;
unsigned char push_val_left=0;
unsigned char pwm_val_right=0;
unsigned char push_val_right=0;
float L_Count=0,R_Count=0;
unsigned int TimerNum=0,SYS_TimeNum=0;
float Save_L_Distance=0,Save_R_Distance=0,Left_Speed=0,Right_Speed=0;
unsigned char Left_point=0,Right_point=0;
unsigned char sys_1ms=0,sys_1s=0,TurnFlag=0;
//初始化PWM调速函数
void Init_Wheel()
{
TMOD = 0x01;
TH0 = 0x0FF;
TL0 = 0x0A4;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void Init_WheelSpeedInter()
{
IT0=1; //INT0下降沿中断
EX0=1; //允许INT1中断
IT1=1; //INT1下降沿中断
EX1=1; //允许INT1中断
EA=1;
}
//得到上一次0.5秒的行驶距离
float GetLeftWheelMileage()
{
return Save_L_Distance;
}
//得到上一次0.25秒的行驶距离
float GetRightWheelMileage()
{
return Save_R_Distance;
}
void Inter_Left(void) interrupt 0
{
L_Count++;
}
void Inter_Right(void) interrupt 2
{
R_Count++;
}
//小车向前函数
void Wheel_Run(char left_val,char right_val)
{
push_val_left=left_val;
push_val_right=right_val;
Left_moto_go ;
Right_moto_go ;
}
//小车后退函数
void Wheel_Back(char left_val,char right_val)
{
push_val_left=left_val;
push_val_right=right_val;
Left_moto_back;
Right_moto_back;
}
//小车停止函数
void Wheel_Stop(void)
{
Wheel_Run(0,0);
}
//左轮PWM调速函数
void pwm_out_left_moto(void)
{
if(pwm_val_left>200)
{
pwm_val_left=0;
}else
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
}
else
{
Left_moto_pwm=0;
}
}
}
//右轮调速函数
void pwm_out_right_moto(void)
{
if(pwm_val_right>200)
{
pwm_val_right=0;
}else
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
}
else
Right_moto_pwm=0;
}
}
//PWM调速中断(TIMER0--工作方式1)
void Wheel_Interrupt(void) interrupt 1
{
TH0 = 0x0FF;
TL0 = 0x0A4;
TimerNum++;
if(TimerNum>=2500)
{
//左右轮速度cm/s
Left_Speed=4*L_Count;
Right_Speed=4*R_Count;
//左右轮0.25秒行驶距离
Save_L_Distance+=L_Count;
Save_R_Distance+=R_Count;
//数据发送到串口图示
DataScope_Get_Channel_Data(L_Count, 1 ); //将数据 1.0 写入通道 1
DataScope_Get_Channel_Data(R_Count, 2 ); //将数据 2.0 写入通道 2
Send_Count = DataScope_Data_Generate(2); //生成10个通道的 格式化帧数据,返回帧数据长度
for( DateNum = 0 ; DateNum < Send_Count; DateNum++) //循环发送,直到发送完毕
{
SendByte(DataScope_OutPut_Buffer[DateNum]);
}
TimerNum=0;
L_Count=0;
R_Count=0;
}
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
⑦ 51单片机直流电机调速问题
if(K1=0) 使用错误,应该是if(K1==0)
满意请采纳