实验三 电机驱动及转速测量实验新板子.docx
《实验三 电机驱动及转速测量实验新板子.docx》由会员分享,可在线阅读,更多相关《实验三 电机驱动及转速测量实验新板子.docx(13页珍藏版)》请在冰豆网上搜索。
实验三电机驱动及转速测量实验新板子
实验三电机驱动及转速测量实验
1实验目的
(1)掌握单片机通用I/O口的使用;
(2)掌握使用单片机定时器产生占空比可调的PWM波;
(3)掌握使用单片机定时器2的捕获功能实现电机转速测量的方法。
2实验电路
2.1实验装置硬件说明
电机控制实验箱的原理框图如图1所示。
图1电机控制实验箱原理框图
从图1可知,控制电机需要两个信号,分别为方向控制和转速控制,控制信号经过驱动电路后驱动电机运转,在电机的轴上安装有塑料转盘,转盘上装有小磁铁,当电机运动时带动小磁铁运动,每个小磁铁经过安装的霍尔传感器后,霍尔传感器都会输出一个脉冲信号,这个脉冲信号在实验中用于检测电机的转速。
电机有两种控制方式,即手动方式和自动方式。
在手动方式时,可以通过开关来控制电机方向;通过旋转电位器可以控制电机速度。
在自动方式时,通过程序来控制电机的方向和转速。
在本实验中,采用信号发生器模拟产生电机转速信号(模拟自动方式),由示波器观察单片机发出的驱动信号(模拟手动方式)。
在下一次电机转速控制中会采用电机。
2.2实验装置接口说明
杜邦线连线
单片机IO口
模块接口
杜邦线数量
功能
P0
J3
8
数码管数据段
P2.2
J2(B)
1
段锁存
P2.3
J2(A)
1
位锁存
P3
J24
8
矩阵键盘数据段
P1.0
示波器
1
输出PWM
P1.1
信号发生器
1
捕获计数
GND
信号发生器、示波器地端
2
共地
3开发环境
程序开发调试软件为KeilC,下载软件为S51ISP,关于这两个软件的使用方法请参考“键盘显示实验指导书”。
4实验要求
(1)通过实验箱上的键盘输入调整PWM波的占空比,具体要求如下:
●当按键为0时,其占空比为20%,LED1显示值为0;
●当按键为1时,其占空比为40%,LED1显示值为1;
●当按键为2时,其占空比为60%,LED1显示值为2;
●当按键为3时,其占空比为80%,LED1显示值为3;
用示波器观察以上PWM波波形。
(2)将测量到的电机转速显示到实验箱的数码管LED3~LED6上,转速单位为“转/分”。
电机转速信号用信号发生器模拟产生。
5例程参考
见附录
6实验报告
(1)绘出硬件原理图
(2)给出软件流程图
(3)写出实验步骤
(4)附上带注释的软件源码,并对各模块进行说明
(5)总结实验心得
7注意事项
(1)实验四的程序建立在本次实验的基础上,本实验中的两个功能(测速、输出PWM)必须要能够同时实现,并不互相影响。
(2)合理分配好定时器资源。
附录:
实验参考程序
#include
ucharPulsNum=0;//脉冲数计数器/
//unsignedintOverFlow=0;//定时器2溢出次数计数器
#defineKeyPortP3
//unsignedcharSpeed=0;
//unsignedcharTime;
#defineDataPortP0//定义数据端口程序中遇到DataPort则用P0替换
sbitLATCH1=P2^2;//定义锁存使能端口段锁存
sbitLATCH2=P2^3;//位锁存
#defineHIGH(65536-10000)/256
#defineLOW(65536-10000)%256
sbitDCOUT=P1^4;//定义电机信号输出端口
sbitDCIN=P1^2;
unsignedcharflag2=0;
unsignedcharflag1=0;
unsignedcharPulsNum=0;//脉冲数计数器
unsignedintOverFlow=0;
unsigneddatal=0;//捕捉值的低8位
unsigneddatah=0;//捕捉值的高8位
unsignedcharPwmL=1500;
unsignedcharPwmH=1500;
unsignedlongCountPerMinute=60000000;//每分钟计数值=fosc/12*60=5*fosc=5*11.0592M
unsignedintspeed=0;
unsignedintdelay_num=10;//速度值
voidCaculateSpeed(unsigneda,unsignedb);
unsignedintTargetSpeed=0,SpeedError,SpeedErrorIntg;
unsignedcharTISignal=0;
/*------------------------------------------------
全局变量
------------------------------------------------*/
unsignedcharPWM_ON;//定义速度等级
#defineCYCLE10//周期
UnsignedcharcodeDuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示段码值0~9
unsignedcharcodeWeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
unsignedcharTempData[8];//存储显示值的全局变量
/*------------------------------------------------
函数声明
------------------------------------------------*/
voidDelayUs2x(unsignedchart);//us级延时函数声明
voidDelayMs(unsignedchart);//ms级延时
voidDisplay(unsignedcharFirstBit,unsignedcharNum);//数码管显示函数
unsignedcharKeyScan(void);//键盘扫描
voidInit_Timer0(void);//定时器初始化
/*------------------------------------------------
主函数
------------------------------------------------*/
voidmain(void)
{
unsignedcharnum;
PWM_ON=0;
Init_Timer0();//初始化定时器0,主要用于数码管动态扫描
//TempData[0]=0x5E;//'d'
//TempData[1]=0x39;//'C'
while
(1)//主循环
{
num=KeyScan();//循环调用按键扫描
if(num==1)//第一个按键,速度等级增加
{
PWM_ON=1;
PwmH=600;
PwmL=2400;
}
elseif(num==2)//第二个按键,速度等级减小
{
PWM_ON=3;
PwmH=1200;
PwmL=1800;
}
elseif(num==3)//第二个按键,速度等级减小
{
PWM_ON=5;
PwmH=1800;
PwmL=1200;
}
elseif(num==4)//第二个按键,速度等级减小
{
PWM_ON=7;
PwmH=2400;
PwmL=600;
}
if(flag2==1){
unsignedk,b,s,g;//k,b,s,g分别代表千位、百位、十位、各位
unsignedintmiddle=0;//定义中间变量,代表计算的余数
if((speed>=0)&&(speed<=9999))
{
//speed=speed/2;
k=speed/1000;//获得千位数值
TempData[0]=DuanMa[k];
middle=speed%1000;//取得剩余3位数
b=middle/100;//获得百位数值
TempData[1]=DuanMa[b];
middle=middle%100;//取得剩余2位数
s=middle/10;//获得十位数值
TempData[2]=DuanMa[s];
g=middle%10;//获得个位数值(剩余1位数)
TempData[3]=DuanMa[g];
}
else//如果速度超过10000,小于变量上限65536
{
TempData[0]=0x80;
//DAT=0x80;//显示一个点'.',dp=1
}
}
//Speed=6000/Time;
//speed=CountPerMinute/(65536*OverFlow+256*a+b);
//TempData[5]=DuanMa[PWM_ON/10];//显示速度等级
TempData[6]=DuanMa[PWM_ON%10];
//TempData[0]=DuanMa[Speed/10];//分解显示信息,如要显示68,
//TempData[1]=DuanMa[Speed%10];//则68/10=668%10=8
}
}
/*------------------------------------------------
uS延时函数
------------------------------------------------*/
voidDelayUs2x(unsignedchart)
{
while(--t);
}
/*------------------------------------------------
mS延时函数
------------------------------------------------*/
voidDelayMs(unsignedchart)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
显示函数
------------------------------------------------*/
voidDisplay(unsignedcharFirstBit,unsignedcharNum)
{
staticunsignedchari=0;
DataPort=0;//清空数据,防止有交替重影
LATCH1=1;//段锁存
LATCH1=0;
DataPort=WeiMa[i+FirstBit];//取位码
LATCH2=1;//位锁存
LATCH2=0;
DataPort=TempData[i];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
i++;
if(i==Num)
i=0;
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
voidInit_Timer0(void)
{EA=1;
TMOD=0x11;//定时器0工作于方式1
//TH0=65535/256;//定时器0计数初值设置TH0=0xff,TH1=0xff,
//TH1=65535%256;//X=65535,2^16-65535=1
ET0=1;//定时器0中断允许
ET1=1;//定时器0中断允许
T2CON=0x09;//定时器2工作在捕捉方式EXEN2=1,CP/非RL2=1
TH2=0x00;//定时器2计数初值设置
TL2=0x00;
ET2=1;//定时器2中断允许
PT2=1;//定时器2中断优先级最高
TR0=1;//启动定时器0
TR2=1;//启动定时器2
TR1=1;
ET1=1;
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
voidTimer0_isr(void)interrupt1
{
if(DCOUT==1)//当前为高电平
{
TH0=(65536-PwmH)>>8;//计数值赋为低电平时间值
TL0=(65536-PwmH);//%256
DCOUT=0;//输出低电平
Display(0,8);
}
elseif(DCOUT==0)//当前为低电平
{
TH0=(65536-PwmL)>>8;//计数值赋为高电平时间值
TL0=(65536-PwmL);//%256
DCOUT=1;//输出高电平
Display(0,8);
}
/*staticunsignedcharcount;
TH0=(65536-1000)/256;//重新赋值2ms
TL0=(65536-1000)%256;
//Display(0,8);//调用数码管扫描
if(count==PWM_ON)
{
DCOUT=0;//如果定时等于on的时间,
//说明作用时间结束,输出低电平
}
count++;
if(count==CYCLE)//反之低电平时间结束后返回高电平
{
count=0;
if(PWM_ON!
=0)//如果开启时间是0保持原来状态
DCOUT=1;
}
*/
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsignedcharKeyScan(void)
{
unsignedcharkeyvalue;
if(KeyPort!
=0xff)
{
flag1=1;
DelayMs(10);
if(KeyPort!
=0xff)
{
keyvalue=KeyPort;
while(KeyPort!
=0xff);
switch(keyvalue)
{
case0xfe:
return1;break;
case0xfd:
return2;break;
case0xfb:
return3;break;
case0xf7:
return4;break;
case0xef:
return5;break;
case0xdf:
return6;break;
case0xbf:
return7;break;
case0x7f:
return8;break;
default:
return0;break;
}
}
}
return0;
}
voidtime2()interrupt5
{
if(EXF2==1)//捕捉引起的中断
{
PulsNum++;//脉冲个数加1
if(PulsNum==1)//定时器清零
{
OverFlow=0;//定时器2溢出次数计数器清零
TH2=0;
TL2=0;
}
elseif(PulsNum==9)//电机转一圈后计算转速
{
TR2=0;
datal=RCAP2L;//读取捕捉值
datah=RCAP2H;
CaculateSpeed(datah,datal);//计算转速
TR2=1;
PulsNum=0;//脉冲个数清零
}
EXF2=0;//清中断标志
}
elseif(TF2)//计数溢出引起的中断
{
OverFlow++;//溢出次数加1
TF2=0;//清中断标志
}
}
/*---定时器1中断服务函数---*/
//staticinttime=0;
voidtime1()interrupt3
{
//TH1=(65536-1000)/256;//重新赋值2ms
//TL1=(65536-1000)%256;
//Display(0,8);//调用数码管扫描
/*TH1=0;
TL1=0;
time++;//每1ms,time加1
if(time>=200)//time加满200次后,1s时间到
{
time=0;//time清零,重新计数
//speed
}
TISignal=~TISignal;*/
}
/*转速计算函数*/
voidCaculateSpeed(unsigneda,unsignedb)
{
//速度=TIMER2每分钟计数值/(溢出计数值+电机转一圈的计数值)
speed=CountPerMinute/(65536*OverFlow+256*a+b);
flag2=1;//电机转速计算完成标志置1
}