基于51单片机的直流电机控制.docx
《基于51单片机的直流电机控制.docx》由会员分享,可在线阅读,更多相关《基于51单片机的直流电机控制.docx(19页珍藏版)》请在冰点文库上搜索。
基于51单片机的直流电机控制
51单片机的直流电机控制
一、试验器件选择
1、控制芯片的作用主要是与L289相连接驱动直流电机,以及与八位数码管相连显示。
(1)、AT89C51是一种带4K自己FLASH存储器的低压、高性能CMOS8为微处理器。
单片机的可擦除只读存储器可以反复擦除1000次。
该器件采用
ATMEL高密度非易失真存储制造技术制造,与工业标准的MCS-51指令集和输出关键相兼容。
由于将多功能8位CPU和闪存组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性奥高且廉价的方案。
(2)、AT89C51引脚图如下:
's!
>XTAL1F0帅00
F'0.1/AD1
PJ2/AD2
XFAL2PJ即河口3
P0.4/^Ft).的心
P口,加口6
RSTPD.TJAD7
P2C/A8PL.
r—
鹏
一
/工a25
四3D
PSEN「20A11
ALEP2,W12
EAP2,5W1.13
IP2,&A14
P27ZA.15
PI.00
PI.1P3.1/TXD
Fl.2P5.2/INT0-
piiPi.^i7nT
P14F3.4E
P15P3.迎
PI.6P3.6/WT
PI.7PITW-
j
2gF二
1Q工
1'
;
3
4
13
5
u
16
17
2、电机驱动芯片
(1)、电机驱动芯片选择L298。
其主要功能是作为单片机与直流电机中间
的过度链接,单片机输出的信号通过L298加载到直流电机上驱动直流电机运行。
其引脚图如下:
U2
L298
(2)、主要工作原理:
1、15脚分别是两个H桥的电流反馈脚,不用时可以直接接地;
2、3为一对输出端口,13、14为一对输出端口;
4为驱动电压输入,最小值必须比输入的低电平高2;
5、7一对输入端口,10、12—对输入端口,TTL电平兼容
6、11使能端,低电平禁止输出;
8、9分别为接地和逻辑电源
3、直流电机。
在protues中选择motor-encoder直流电机,引脚图如下:
上方左右的两个引脚在点击运转时输出频
率相同的方波,但是在相位上相差90,而且
在正转和反转是相反,因此可以根据这两个引
脚的输出情况判断点击的转向。
上方中间的引
脚每当电机转一圈就输出一个正脉冲,可以据此册数点击的转速。
左
右两个引脚是电机的电压输入端。
4、74HC74。
当D触发器的D和CLK输入端分别接电机上方的左右两个输出
端口时可以根据D触发器的输出情况判断点击的转速。
5、八位数码管。
用以显示。
二、系统硬件设计连接
1、系统的器件连接图如下:
2、单片机与数码管通过P0口和P2口相连,其中P2口选择点亮哪一个数码管,
P0口则控制被点亮的数码管显示的数据。
3、单片通过P1A0和P1A1和L298的第一对输入端IN1和IN2相连,然后又
L298的第一对输出端OUT1和OUT2与直流电机相连,已达到控制直流电机的目的。
4、从PW4到P1A7分别接一个Button按钮来实现PID控制,P3A6和P3A7分别接Button按钮实现对电机的加速与减速控制。
5、双刀双掷开关SW1课实现点击的正转与反转,单刀双掷开关SW2可实现点
击的开启与停止
三、系统程序设计及功能实现
1、程序流程图:
输入一个值,点击Enter按
钮,通过PID算法,改变
PWM波输出让电机运行
循环
通过按钮加减改变当前值,
差值,将差值加到原值上,
通过PID算法改变PWM波
(1)、普通延时:
2、各部分实现程序:
#include
voiddelayms(unsignedcharx)
P0
0;P2=0xbf;P0
/10];
P0=
10];
//关闭显
{
unsignedchari;
while(x--)
for(i=0;i<120;i++);
}
2)、数码管显示:
#include
#include
#include
voiddisplay_lilun(doublenum)
{
charcodetable[]={
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,//0~7对应数
码
0x7f,0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71};//8~F对应数码
longintn=num;
P0=0;P2=0x7f;P0=
table[n%1000/100];
table[n%100
delayms
(2);//十位
P0=0;P2=0xdf;
table[n%
delayms
(2);//个位
P0=0;
二aa
示器
}
voiddisplay(doublenum,intdir)
{
charcodetable[]={
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,//0~7对应数
码
0x7f,0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71};//8~F对应数码
longintn=num*10;
P0=0;P2=0xf7;P0=table[n
/1000];delayms
(2);//百位
加小数点
delayms
(2);//百位加小数点
P0
0;P2=0xfb;P0
P0=0;
//关闭显
table[n%1000/100];
delayms
(2);//百位加小数点
P0=0;P2=0xfd;P0=table[n%100/10]+128;
delayms
(2);//十位
P0=0;P2=0xfe;P0=table[n%10];
delayms
(2);//个位
示器
if(dir==1)
{
P0=0;P2=0xef;P0=0x40;delayms
(2);
}
}
3)、按键扫描:
#include
sbitjiashi=P1A3;
个按钮进行位定义
sbitjianshi=P1A4;
sbitjia=P1A5;
sbitjian=P1A6;
sbitenter=P1A7;
externintnum_key[5];
义全局变量
voidkeyscan()
//对各{
if(jiashi==0)
{
while(!
jiashi);
num_key[0]++
}
//定if(jianshi==0)
{
while(!
jianshi);
num_key[1]++;
}
if(jia==0)
{
while(!
jia);
num_key[2]++;
}
if(jian==0)
{
while(!
jian);
num_key[3]++;
}
if(enter==0)
{
while(!
enter);
num_key[4]++;
}
}
4)、PWM波输出:
#include
#include
#include
externintPWM;//赋初值
externintstart,sudu_lilun;
externdoubledis_count;
sbitS2=P3A6;//PWM
值减少键
sbitS3=P3A7;//PWM
值增加键
voidPWM_duty()
{
if(start>=1)
PWM=sudu_lilun;
do
{
if(PWM!
=0xff)
{
PWM++;
delayms(10);
}
}
while(S3==0);
do
delayms(10);
{
if(PWM>=0x02)
{
PWM--;
}
}
while(S2==0);
}
5)、中断服务程序:
#include
externint
PWM,count,count1,dir,count20
ms_flag;
externdoubledis_count;
sbitPWM_OUT1=P1A1;
sbitPWM_OUT2=P1A0;
voidtimer0()interrupt1
{
TL0=0x00;
TH0=0xd8;//10ms
TL0=0xf0;
TH1=PWM;
TR1=1;
PWM_OUT1=0;//启动输
出
PWM_OUT2=0;
if(i++==492)
{
count20ms_flag=1;
longinti;
i=0;
TR1=0;
dir=0;
dis_count=(double)(count+co
unt1)/2;
count=0;
count1=0;
}
}
voidtimer1()interrupt3
{
TR1=0;
if(dir==0)
{
PWM_OUT1=1;//结
束输出
PWM_OUT2=0;
}
else
{
PWM_OUT1=0;
PWM_OUT2=1;
}
}
{
EX0=0;
count++;
EX0=1;
}
voidEIRQ1(void)interrupt2
{
EX1=0;
count1++;
EX1=1;
}
6))、PID控制:
#include
#include
intP,I,D;
externintsudu_lilun;
typedefstructPID//定义结
构体
{
intSetPoint;//目标
longSumError;//误差
voidEIRQ0(void)interrupt0
doubleProportion;//比例系数
doubleIntegral;//积分系数intIncPIDCalc(intNextPoint)
doubleDerivative;//微分系数
intLastError;
intPrevError;
}PID;
staticPIDsPID;
staticPID*sptr=&sPID;
voidIncPIDInit()
{
sptr->SumError=0;
sptr->LastError=0;//Error[-1]
sptr->PrevError=0;//Error[-2]
sptr->Proportion=0.5;//比例
系数
sptr->Integral=0.3;//积分系数
sptr->Derivative=0.3;//微分系
数
sptr->SetPoint=sudu_lilun;
}
{
registerintiError,iIncpid;//当
前的误差值
iError=sptr->SetPoint-
NextPoint;//计算增加量
iIncpid=sptr->Proportion*
iError//E[k]项
-sptr->Integral*
sptr->LastError//E[k-1]项
+sptr->Derivative*
sptr->PrevError;//E[k-2]项
//存储当前误差以便后面计算
sptr->PrevError=
sptr->LastError;
sptr->LastError=iError;
//返回增量值
return(iIncpid);
}
7)、main函数:
#include
#include
#include
dir=1;
#include
#include
#include
#include
sbitP10=P1A2;〃确定电机转
向
intnum_key[5];
int
PWM,PWM1,count,count1,dir,su
du_lilun,start,count20ms_flag;
doubledis_count;
intPWM_PID;
voidinit();
voidmain()
{
init();
while
(1)
{
PWM_duty();
if(P10==1)
dir=0;
keyscan();
sudu_lilun=num_key[0]*10-
num_key[1]*10+num_key[2]-
num_key[3];
display_lilun(sudu_lilun);
if(num_key[4]==1)
start=1;
display(dis_count,dir);
if(start>=1&&count20ms_flag
==1)
{
count20ms_flag=0;
IncPIDInit();
PWM_PID=IncPIDCalc(dis_count);
PWM=PWM+PWM_PID*2;
else
IT1=1;
}
voidinit()
器、外部中断初始化
{
TMOD=0x01;
TH0=0xd8;
TL0=0xf0;
IT0=1;
EX0=1;
EX1=1;
〃定时TH1=PWM;
TL1=0xff;
EA=1;
ET0=1;
ET1=1;
TR0=1;
}
3、程序实现效果: