51系列单片机直流电机闭环调速实验.docx
- 文档编号:28975245
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:24
- 大小:110.43KB
51系列单片机直流电机闭环调速实验.docx
《51系列单片机直流电机闭环调速实验.docx》由会员分享,可在线阅读,更多相关《51系列单片机直流电机闭环调速实验.docx(24页珍藏版)》请在冰豆网上搜索。
51系列单片机直流电机闭环调速实验
1、实验名称:
51系列单片机直流电机闭环调速实验
基于Protuse仿真实验平台实现
2、实验内容(实验原理介绍):
1、直流电机调速原理
图1所示电枢电压为V,电枢电流I,电枢回路总电阻为R,电机常数C,励磁磁通量Φ。
那么根据KVL方程:
电机转速
其中,对于极对数为P,匝数为N,电枢支路数为a的电机来说:
电机常数
,意味着电机确定后,该值是不变的。
而在V-IR中,由于R仅为绕组电阻,导致IR非常小,所以V-IR≈V。
由此可见我们改变电枢电压,转速n即可随之改变。
实现直流电机的闭环调速
实现原理如下图所示:
2、测速软件设计
图12软件测速的方框图
/****T1中断服务程序********单位时间(S)方波的个数*************/
voidtime1_int(void)interrupt3
{
count_speed++;
if(count_speed==20)
{count_speed=0;
num_display=num_medium;
num_medium=0;
}
}
3、PID算法的数字实现
由于DDC(DirectDigitalControl)系统是一种时间离散控制系统。
因此,为了用微机实现(式3-1-1)必须将其离散化,
用数字形式的差分方程来代替连续系统的微分方程。
离散化的PID表达式为:
(式3-1-2)
式中,
——采样周期;
——第n次采样时微机输出;
——第n次采样时的偏差值;
——第n-1次采样时的偏差值;
——采样序号,n=0,1,2,…。
通常把(式3-1-2)称为PID的位置控制算式。
根据(式3-1-2)可以进一步推导出离散化的位置型PID编程表达式,如(式3-1-3):
第K次采样PID的输出式为:
(式3-1-3)
其中,设
式中,
确定了
的值后,实现(式3-1-3)的编程框图如右图所示:
由(式3-1-3)还可得离散化的位置型P控制和PI控制的编程表达式。
它们各自的编程框图也只需在该图的基础上稍作删减即可。
4、调速设计方案
调速采用PWM(PulseWidthModulation)脉宽调制,工作原理:
通过产生矩形波,改变占空比,以达到调整脉宽的目的。
PWM的定义:
脉宽调制(PWM)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
模拟信号的值可以连续变化,其时间和幅度的分辨率都没有限制。
9V电池就是一种模拟器件,因为它的输出电压并不精确地等于9V,而是随时间发生变化,并可取任何实数值。
与此类似,从电池吸收的电流也不限定在一组可能的取值范围之内。
模拟信号与数字信号的区别在于后者的取值通常只能属于预先确定的可能取值集合之内,例如在{0V,5V}这一集合中取值。
模拟电压和电流可直接用来进行控制,如对汽车收音机的音量进行控制。
在简单的模拟收音机中,音量旋钮被连接到一个可变电阻。
拧动旋钮时,电阻值变大或变小;流经这个电阻的电流也随之增加或减少,从而改变了驱动扬声器的电流值,使音量相应变大或变小。
与收音机一样,模拟电路的输出与输入成线性比例。
尽管模拟控制看起来可能直观而简单,但它并不总是非常经济或可行的。
其中一点就是,模拟电路容易随时间漂移,因而难以调节。
能够解决这个问题的精密模拟电路可能非常庞大、笨重(如老式的家庭立体声设备)和昂贵。
模拟电路还有可能严重发热,其功耗相对于工作元件两端电压与电流的乘积成正比。
模拟电路还可能对噪声很敏感,任何扰动或噪声都肯定会改变电流值的大小。
通过以数字方式控制模拟电路,可以大幅度降低系统的成本和功耗。
此外,许多微控制器和DSP已经在芯片上包含了PWM控制器,这使数字控制的实现变得更加容易了。
5、电路原理图
三、实验结果分析(含程序、数据记录及分析和实验总结等,可附页):
1、51系列单片机直流电机闭环调速实验程序
/*--------------------------------------------------------------------------
REG52.H
Headerfileforgeneric80C52and80C32microcontroller.
Copyright(c)1988-2002KeilElektronikGmbHandKeilSoftware,Inc.
Allrightsreserved.
--------------------------------------------------------------------------*/
#ifndef__REG52_H__
#define__REG52_H__
/*BYTERegisters*/
sfrP0=0x80;
sfrP1=0x90;
sfrP2=0xA0;
sfrP3=0xB0;
sfrPSW=0xD0;
sfrACC=0xE0;
sfrB=0xF0;
sfrSP=0x81;
sfrDPL=0x82;
sfrDPH=0x83;
sfrPCON=0x87;
sfrTCON=0x88;
sfrTMOD=0x89;
sfrTL0=0x8A;
sfrTL1=0x8B;
sfrTH0=0x8C;
sfrTH1=0x8D;
sfrIE=0xA8;
sfrIP=0xB8;
sfrSCON=0x98;
sfrSBUF=0x99;
/*8052Extensions*/
sfrT2CON=0xC8;
sfrRCAP2L=0xCA;
sfrRCAP2H=0xCB;
sfrTL2=0xCC;
sfrTH2=0xCD;
/*BITRegisters*/
/*PSW*/
sbitCY=PSW^7;
sbitAC=PSW^6;
sbitF0=PSW^5;
sbitRS1=PSW^4;
sbitRS0=PSW^3;
sbitOV=PSW^2;
sbitP=PSW^0;//8052only
/*TCON*/
sbitTF1=TCON^7;
sbitTR1=TCON^6;
sbitTF0=TCON^5;
sbitTR0=TCON^4;
sbitIE1=TCON^3;
sbitIT1=TCON^2;
sbitIE0=TCON^1;
sbitIT0=TCON^0;
/*IE*/
sbitEA=IE^7;
sbitET2=IE^5;//8052only
sbitES=IE^4;
sbitET1=IE^3;
sbitEX1=IE^2;
sbitET0=IE^1;
sbitEX0=IE^0;
/*IP*/
sbitPT2=IP^5;
sbitPS=IP^4;
sbitPT1=IP^3;
sbitPX1=IP^2;
sbitPT0=IP^1;
sbitPX0=IP^0;
/*P3*/
sbitRD=P3^7;
sbitWR=P3^6;
sbitT1=P3^5;
sbitT0=P3^4;
sbitINT1=P3^3;
sbitINT0=P3^2;
sbitTXD=P3^1;
sbitRXD=P3^0;
/*SCON*/
sbitSM0=SCON^7;
sbitSM1=SCON^6;
sbitSM2=SCON^5;
sbitREN=SCON^4;
sbitTB8=SCON^3;
sbitRB8=SCON^2;
sbitTI=SCON^1;
sbitRI=SCON^0;
/*P1*/
sbitT2EX=P1^1;//8052only
sbitT2=P1^0;//8052only
/*T2CON*/
sbitTF2=T2CON^7;
sbitEXF2=T2CON^6;
sbitRCLK=T2CON^5;
sbitTCLK=T2CON^4;
sbitEXEN2=T2CON^3;
sbitTR2=T2CON^2;
sbitC_T2=T2CON^1;
sbitCP_RL2=T2CON^0;
#endif
#ifndefTEST_H
#defineTEST_H
#defineu8unsignedchar
#defineu16unsignedint
//////LCD////
sbitRS=P2^0;
sbitRW=P2^1;
sbitEN=P2^2;
//////L298/////
sbitIN1=P2^5;
sbitIN2=P2^6;
sbitENA=P2^7;
voiddelay_ms(u16z);
voidLCD_WriteData(u8Dat);
voidLCD_WriteCOM(u8com);
voidShow_Num(u8x,u8y,u16num);
voidShow_fNum(u8x,u8y,u16num);
voidLCD_Init(void);
voidset_Dir(u8dir);
voidkey_scan(void);
externvoidtimer_init();
externvoidtimer0();
externu16count;
externu8num;
externu16set_value;
externu8kp,ki,kd;
#endif
#ifndefSPEED_H
#defineSPEED_H
externu16count;
externu8pulse;
externvoidShow_Num(u8x,u8y,u16num);
#endif
#include
#include"test.h"
u8Dir=1;//方向
/*************
函数功能:
延时
****************/
voiddelay_ms(u16z)
{
u16i;
u8j;
for(i=z;i>0;i--)
for(j=120;j>0;j--);
}
/*************
函数功能:
LCD写数据
****************/
voidLCD_WriteData(u8Dat)
{
RS=1;
delay_ms(5);
P0=Dat;
EN=1;
delay_ms(20);
EN=0;
//delay_ms(15);
}
/*************
函数功能:
LCD命令
****************/
voidLCD_WriteCOM(u8com)
{
RS=0;
delay_ms(5);
P0=com;
EN=1;
delay_ms(20);
EN=0;
//delay_ms(15);
}
/*************
函数功能:
Show_Num初始化
****************/
voidShow_Num(u8x,u8y,u16num)
{
u8a,b,c;
a=num/100;
b=num/10%10;
c=num%10;
if(y%2==1)
LCD_WriteCOM(0x80+x);
else
LCD_WriteCOM(0x80+0x40+x);
LCD_WriteData(a+0x30);
LCD_WriteData(b+0x30);
LCD_WriteData(c+0x30);
}
/*************
函数功能:
Show_fNum初始化
****************/
voidShow_fNum(u8x,u8y,u16num)
{
u8a,b;
a=num/10%10;
b=num%10;
if(y%2==1)
LCD_WriteCOM(0x80+x);
else
LCD_WriteCOM(0x80+0x40+x);
LCD_WriteData(a+0x30);
LCD_WriteData(b+0x30);
}
/*************
函数功能:
Show_Num初始化
****************/
voidShow_char(u8x,u8y,u8ch)
{
if(y%2==1)
LCD_WriteCOM(0x80+x);
else
LCD_WriteCOM(0x80+0x40+x);
LCD_WriteData(ch);
}
/*************
函数功能:
LCD固定显示
****************/
voidLCD_Dispaly(void)
{
Show_char(0,1,'P');//实际测量值
Show_char(1,1,'V');
Show_char(2,1,':
');
Show_Num(3,1,0);
Show_char(9,1,'S');//设定值
Show_char(10,1,'V');
Show_char(11,1,':
');
Show_Num(12,1,set_value);
Show_char(0,2,'P');//P实际测量值
Show_char(1,2,':
');
Show_fNum(2,2,kp);
Show_char(6,2,'I');//I实际测量值
Show_char(7,2,':
');
Show_fNum(8,2,ki);
Show_char(12,2,'D');//D实际测量值
Show_char(13,2,':
');
Show_fNum(14,2,kd);
}
/*************
函数功能:
LCD初始化
****************/
voidLCD_Init(void)
{
RW=0;
EN=0;
delay_ms(20);
LCD_WriteCOM(0x38);
LCD_WriteCOM(0x0c);
LCD_WriteCOM(0x06);
LCD_WriteCOM(0x01);
LCD_Dispaly();
}
/*************
函数功能:
设置转向
****************/
voidset_Dir(u8dir)
{
if(dir)
{
IN1=1;
IN2=0;
}
else
{
IN1=0;
IN2=1;
}
ENA=1;
}
intmain(void)
{
LCD_Init();
set_Dir(Dir);
timer_init();
EA=1;
while
(1)
{
key_scan();
Show_Num(3,1,count);
}
return0;
}
voidkey_scan(void)
{
u8Temp=P1;
staticu8Add_Ver=0,one_ten=0;
staticTri=0,CON=0;
Temp=Temp^0xff;
Tri=Temp&(Temp^CON);
CON=Temp;
if(Tri==0x10)
{Add_Ver++;Add_Ver=Add_Ver%2;}
elseif(Tri==0x20)
{one_ten++;one_ten=one_ten%2;}
elseif(Tri==0x01)
{
if(set_value+1<=230&&Add_Ver==0&&one_ten==0)
set_value++;
elseif(set_value>=1&&Add_Ver==1&&one_ten==0)
set_value--;
elseif(set_value+10<=230&&Add_Ver==0&&one_ten==1)
set_value=set_value+10;
elseif(set_value>=10&&Add_Ver==1&&one_ten==1)
set_value=set_value-10;
Show_Num(12,1,set_value);
}
elseif(Tri==0x02)
{
if(kp+1<=100&&Add_Ver==0&&one_ten==0)
kp++;
elseif(kp>=1&&Add_Ver==1&&one_ten==0)
kp--;
elseif(kp+10<=100&&Add_Ver==0&&one_ten==1)
kp=kp+10;
elseif(kp>=10&&Add_Ver==1&&one_ten==1)
kp=kp-10;
Show_fNum(2,2,kp);
}
elseif(Tri==0x04)
{
if(ki+1<=100&&Add_Ver==0&&one_ten==0)
ki++;
elseif(ki>=1&&Add_Ver==1&&one_ten==0)
ki--;
elseif(ki+10<=100&&Add_Ver==0&&one_ten==1)
ki=ki+10;
elseif(ki>=10&&Add_Ver==1&&one_ten==1)
ki=ki-10;
Show_fNum(8,2,ki);
}
elseif(Tri==0x08)
{
if(kd+1<=100&&Add_Ver==0&&one_ten==0)
kd++;
elseif(kd>=1&&Add_Ver==1&&one_ten==0)
kd--;
elseif(kd+10<=100&&Add_Ver==0&&one_ten==1)
kd=kd+10;
elseif(kd>=10&&Add_Ver==1&&one_ten==1)
kd=kd-10;
Show_fNum(14,2,kd);
}
}
#include
#include"timer.h"
#include"test.h"
u16count=0;//脉冲计数
u8num=0;
u8time=0;
u8num1=0,pulse=50;
/*************
函数功能:
计数初始化
****************/
voidtimer0_init()
{
TMOD|=0X05;
TH0=0;
TL0=0;
TR0=1;
}
/*************
函数功能:
定时器1初始化
****************/
voidtimer1_init()
{
TMOD|=0x10;
TH1=(65535-50000)/256;//20ms
TL1=(65535-50000)%256;
TR1=1;
ET1=1;
}
/*************
函数功能:
定时器2初始化
****************/
voidtimer2_init()
{
RCAP2H=(65536-100)/256;//50us
RCAP2L=(65536-100)%256;
TH2=RCAP2H;
TL2=RCAP2L;
ET2=1;
TR2=1;
}
/*************
函数功能:
定时器初始化
****************/
voidtimer_init()
{
timer0_init();
timer1_init();
timer2_init();
}
voidtimer0()interrupt3
{
//EA=0;
TH1=(65535-50000)/256;//25ms
TL1=(65535-50000)%256;
num++;
if(num>=4)//100ms
{
num=0;
count=TL0;
TL0=0;
TH0=0;
speed();
}
//EA=1;
}
voidtimer2()interrupt5
{
TF2=0;
num1++;
if(num1>=pulse)
IN1=0;
if(num1>=PULSE)
{IN1=1;num1=0;}
}
#include
#include"test.h"
#include"speed.h"
u16set_value=100;
u8kp=25,ki=10,kd=15;
intuk=0;
/****************
函数功能:
设定速度
****************/
voidset_speed(u8value)
{
staticintessd=0,essd1=0,essd2=0;
essd=value-count;
uk=kp*essd+ki*essd1+kd*(essd-essd2);
essd2=essd;
essd1+=essd;
//uk=(int)(uk/100)+(int)(100*value/240);
uk=(int)(uk/100);
if(uk<0)
pulse=0;
elseif(uk<100)
pulse=uk;
else
pulse=99;
//Show_Num(0,2,uk);
}
voidspeed(void)
{
set_speed(set_value);
}
2、实验总结
经过这次的实验,我又一次加深了对LED的认识和加强了对keil以及Protues等软件的使用技能。
虽然之前做过很多的实验,但是自己任然存在很大的问题。
在本次实验中任然有很多东西不会,所以又重新学了一遍单片机,加大了对单片机学习的兴趣。
刚开始做实验时是很盲目的,胡乱的查资料。
所以经过这次的实验我明白了做任何事之前都
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 51 系列 单片机 直流电机 闭环 调速 实验
![提示](https://static.bdocx.com/images/bang_tan.gif)