基于51单片机的直流电机控制.docx

上传人:b****5 文档编号:8513566 上传时间:2023-01-31 格式:DOCX 页数:13 大小:170.36KB
下载 相关 举报
基于51单片机的直流电机控制.docx_第1页
第1页 / 共13页
基于51单片机的直流电机控制.docx_第2页
第2页 / 共13页
基于51单片机的直流电机控制.docx_第3页
第3页 / 共13页
基于51单片机的直流电机控制.docx_第4页
第4页 / 共13页
基于51单片机的直流电机控制.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

基于51单片机的直流电机控制.docx

《基于51单片机的直流电机控制.docx》由会员分享,可在线阅读,更多相关《基于51单片机的直流电机控制.docx(13页珍藏版)》请在冰豆网上搜索。

基于51单片机的直流电机控制.docx

基于51单片机的直流电机控制

 

基于51单片机的

直流电机控制

 

一、试验器件选择

1、控制芯片的作用主要是与L289相连接驱动直流电机,以及与八位数码管相连显示。

(1)、AT89C51是一种带4K自己FLASH存储器的低压、高性能CMOS8为微处理器。

单片机的可擦除只读存储器可以反复擦除1000次。

该器件采用ATMEL高密度非易失真存储制造技术制造,与工业标准的MCS-51指令集和输出关键相兼容。

由于将多功能8位CPU和闪存组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。

AT89C51单片机为很多嵌入式控制系统提供了一种灵活性奥高且廉价的方案。

(2)、AT89C51引脚图如下:

2、电机驱动芯片

(1)、电机驱动芯片选择L298。

其主要功能是作为单片机与直流电机中间的过度链接,单片机输出的信号通过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、单片通过P1^0和P1^1和L298的第一对输入端IN1和IN2相连,然后又L298的第一对输出端OUT1和OUT2与直流电机相连,已达到控制直流电机的目的。

4、从P1^4到P1^7分别接一个Button按钮来实现PID控制,P3^6和P3^7分别接Button按钮实现对电机的加速与减速控制。

5、双刀双掷开关SW1课实现点击的正转与反转,单刀双掷开关SW2可实现点击的开启与停止。

 

三、系统程序设计及功能实现

1、程序流程图:

 

2、各部分实现程序:

(1)、普通延时:

#include

voiddelayms(unsignedcharx)

{

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];delayms

(2);//百位加小数点

P0=0;P2=0xbf;P0=table[n%100/10];delayms

(2);//十位

P0=0;P2=0xdf;P0=table[n%10];delayms

(2);//个位

P0=0;//关闭显示器

}

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);//百位加小数点

P0=0;P2=0xfb;P0=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);//个位

P0=0;//关闭显示器

if(dir==1)

{

P0=0;P2=0xef;P0=0x40;delayms

(2);

}

}

 

(3)、按键扫描:

#include

sbitjiashi=P1^3;//对各个按钮进行位定义

sbitjianshi=P1^4;

sbitjia=P1^5;

sbitjian=P1^6;

sbitenter=P1^7;

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=P3^6;//PWM值减少键

sbitS3=P3^7;//PWM值增加键

voidPWM_duty()

{

if(start>=1)

PWM=sudu_lilun;

do

{

if(PWM!

=0xff)

{

PWM++;

delayms(10);

}

}

while(S3==0);

do

{

if(PWM>=0x02)

{

PWM--;

delayms(10);

}

}

while(S2==0);

}

 

(5)、中断服务程序:

#include

externintPWM,count,count1,dir,count20ms_flag;

externdoubledis_count;

sbitPWM_OUT1=P1^1;

sbitPWM_OUT2=P1^0;

voidtimer0()interrupt1

{

longinti;

TR1=0;

dir=0;

TL0=0x00;

TH0=0xd8;//10ms

TL0=0xf0;

TH1=PWM;

TR1=1;

PWM_OUT1=0;//启动输出

PWM_OUT2=0;

if(i++==492)

{

count20ms_flag=1;

i=0;

dis_count=(double)(count+count1)/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;

}

}

voidEIRQ0(void)interrupt0

{

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;//误差

doubleProportion;//比例系数

doubleIntegral;//积分系数

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;

}

intIncPIDCalc(intNextPoint)

{

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

#include

#include

#include

#include

sbitP10=P1^2;//确定电机转向

intnum_key[5];

intPWM,PWM1,count,count1,dir,sudu_lilun,start,count20ms_flag;

doubledis_count;

intPWM_PID;

voidinit();

voidmain()

{

init();

while

(1)

{

PWM_duty();

if(P10==1)

dir=0;

else

dir=1;

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;

}

}

}

voidinit()//定时器、外部中断初始化

{

TMOD=0x01;

TH0=0xd8;

TL0=0xf0;

IT0=1;

EX0=1;

IT1=1;

EX1=1;

TH1=PWM;

TL1=0xff;

EA=1;

ET0=1;

ET1=1;

TR0=1;

}

3、程序实现效果:

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1