📄 电机无级调制控制系统.cpp
字号:
/* 电机无级调速控制系统 */
#include <stdio.h>
#include <conio.h>
#include "ApiEx.h"
#pragma comment(lib,"ApiEx.lib")
#define ioport 0x2b0 //8279 数据口
#define ioport1 0x2b1 //8279 控制口
#define time 0x280 //8253 定时器0口地址
#define time1 0x281 //8253 定时器1口地址
#define timec 0x283 //8253 控制口地址
int k;
int disled[6]={0x00,0x00,0x00,0x00,0x00,0x00};//led从右到左显示,最左显示功能键
int realkey[4]={0x00,0x00,0x00,0x00};//得到真实的按键值
int led[] ={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,
0x39,0x5E,0x79,0x71,0x80,0x40};//0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F,g,m,P,r,w,x,y,.,-
int table[]={0x1b,0x13,0x0b,0x03,0x1a,0x12,0x0a,0x02,0x19,0x11,0x09,0x01,0x18,0x10,0x08,0x00};
int keyin=0;
void key(); //键盘显示
void disp(); //显示
void int_proc(); //中断处理程序
void motorstart();//启动电机
void measurespeed();//测量转速
void pidadapt();//PID调速
int funkey=0;//0表示是功能键,1表示数字键
int datakey=0;//表示之前未按功能键,1表示按下了功能键
int keydatanum=0;//表示按下数字键的个数
int keycdown=0;//表示按下了E键
int keyedown=0;//表示按下了C键
int keyadaptspeed=0xff;
int getspeed=0;//测得的转速
int j=0;
int jj=0;
int d=0;//存放给定的速度换算成高电平持续时间
int saved=0;
int keysave=0;//保存初始转速的键值
BYTE data;//存放按键值
BYTE data1=0x00;//存计数的低8位
BYTE data2=0x00;//存计数的高8位
int count=0;//得到定时器2的当前计数值
int count1=0;//测到的转速值
int mspeed[2]={0x00,0x00};
void main()
{
printf("--------------------EXP29_21_SYB---------------------\n");
printf("Press any key to begin!\n\n");
getch();
printf("Press small keybord:\n");
printf("A--please input the given speed;\n");
printf("B--STOP MOTOR \n");
printf("c--start the motor according the given speed;\n");
printf("F--EXIT\n");
if(!Startup()) /*打开设备*/
{
printf("ERROR: Open Device Error!\n");
return;
}
PortWriteByte(ioport1,0xd3); //8279 清零
PortWriteByte(ioport1,0x40); //读FIFO存储器命令
PortWriteByte(ioport1,0x00); //置键盘显示模式
PortWriteByte(ioport1,0x80); //写显示缓冲区命令
PortWriteByte(0x283,0x36); //设置8253工作方式,定时器0工作方式3
PortWriteByte(0x280,0x50); //设置定时器0的初始计数值50000,低位为50
PortWriteByte(0x280,0xc3); //设置定时器0的初始计数值50000,高位为c3产生50ms的脉冲
PortWriteByte(0x283,0xb0); //设置8253工作方式,定时器2工作方式0,(计脉冲的个数)
PortWriteByte(0x282,0xff); //设置定时器2的初始计数值ffff,低位为ff
PortWriteByte(0x282,0xff); //设置定时器2的初始计数值ffff,高位为ff
PortWriteByte(0x28b,0x81); //设置8255工作方式,C口低四位输入, C口高四位输出,A口输入,B口输入
PortWriteByte(0x283,0x50); //设置8253工作方式,定时器1工作方式0
PortWriteByte(0x281,0x0a); //设置定时器1的初始计数值20,低位为14,定时1s
RegisterLocalISR(int_proc); /*注册中断程序*/
EnableIntr(); /*开中断*/
do{
key(); //调键盘显示子程序
if(keyin==0x0a) //是否'a'命令,启动输入电机起始值
{
disled[5]=led[0x0a];//显示键A
for(jj=0;jj<4;jj++)//清真实的数字键值
{ realkey[jj]=0; }
disled[0]=led[0];//显示给定值为00
disled[1]=led[0];
disled[2]=led[0];//显示测速值为00
disled[3]=led[0];
funkey=0;//表示按下了功能键
keycdown=0;//表示没有按下功能键E
keyedown=0;//表示没有按下功能键C
datakey=1;//表示当前按下A功能键
mspeed[0]=0;//测定的速度显示为00
mspeed[1]=0;
d=0;//给定的脉宽值为0
}
else if(keyin==0x0b) //是否'b' 命令,停止电机
{
disled[5]=led[0x0b];//显示键B
disled[0]=led[0];//显示给定值为00
disled[1]=led[0];
disled[2]=led[0];//显示测速值为00
disled[3]=led[0];
disled[4]=0x00;
for(jj=0;jj<4;jj++)
{
realkey[jj]=0;
}
mspeed[0]=0;//测定的速度显示为00
mspeed[1]=0;
funkey=0;//表示按下了功能键
keycdown=0;//表示没有按下功能键E
keyedown=0;//表示没有按下功能键C
datakey=0;//表示当前没按下A功能键
d=0;//给定的脉宽值为0
keydatanum=0; //计录的按下数字键值为0个
PortWriteByte(0x290,0x80); /*D/A 输出*/
}
else if(keyin==0x0c) //是否'c' 命令,按照a给定的值使电机转动
{
d=realkey[0]+realkey[1]*10;
disled[5]=led[0x0e];
disled[0]=led[realkey[0]];//显示给定值
disled[1]=led[realkey[1]];
disled[2]=led[0];//显示测速值为0
disled[3]=led[0];
disled[4]=0x00;
mspeed[0]=0;//测定的速度显示为00
mspeed[1]=0;
funkey=0;//表示按下了功能键
keycdown=1;//表示没有按下功能键C
keyedown=0;//表示按下功能键E
keydatanum=0; //计录的按下数字键值为0个
disled[2]=led[mspeed[0]];//显示测速值的低位
disled[3]=led[mspeed[1]];//显示测速值的高位
}
else //按下的是数字键
{
mspeed[0]=0;//测定的速度显示为00
mspeed[1]=0;
if ((datakey==1)&&(keycdown==0))//如果按下了A键之后,可以继续按数字键,此时输入的是给定的转速值
{
keycdown=0;//表示没有按下功能键C
keyedown=0;//表示按下功能键E
d=0;//给定的脉宽值为0
keysave=keyin;
keydatanum++;
realkey[keydatanum-1]=keyin;
disled[keydatanum-1]=led[keysave];
disled[2]=led[0];
disled[3]=led[0];
disled[4]=0x00;
}
}
}
while(!(keyin==0x0f)); //'f'命令,退出程序
d=0;
PortWriteByte(0x290,0x80); /*D/A 输出*/
PortWriteByte(ioport1,0xd1); //清显示
DisableIntr(); /*关中断*/
Cleanup(); /*关闭设备*/
}
void key()
{
PortWriteByte(ioport1,0xd1); //清显示
PortWriteByte(0x290,0x80); /*D/A 输出*/
Sleep(100);
do{
disp(); //调显示子程序
if(keycdown==1)//C键
{
motorstart();//电机开始转动
if(keyedown==1)//如果进入调速函数
{
pidadapt();
}
}
PortReadByte(ioport1,&data);
}
while(!(data&0x07));
PortReadByte(ioport,&data); //读状态
keyin = data & 0x07;
data = data & 0x3f;
for(k=0;k<16;k++)
{
if(data==table[k])
keyin=k;
}
}
//数码管显示,最高位(最左)显示当前功能键,最右两位显示给定值,第三、四位显示测速值
//由void key()函数调用
void disp()
{
PortWriteByte(ioport1,0x90);
Sleep(100);
PortWriteByte(ioport,disled[0]);
PortWriteByte(ioport,disled[1]);
PortWriteByte(ioport,disled[2]);
PortWriteByte(ioport,disled[3]);
PortWriteByte(ioport,disled[4]);
PortWriteByte(ioport,disled[5]);
}
//中断处理程序,定时1s,由void measurespeed()进入
void int_proc()
{
getspeed=0;
data1=0x00;//存计数的低8位
data2=0x00;//存计数的高8位
count=0;//得到定时器2的当前计数值
count1=0;//测到的转速值
PortReadByte(0x282,&data1); //读入计数器的低8位
PortReadByte(0x282,&data2); //读入计数器的高8位
count=data2*256+data1;
count1=(65535-count)*2/6; //得到转速
getspeed=count1;
printf("getspeed=%d\n",getspeed);
mspeed[0]=getspeed%10;//得到测到的转速的低位
mspeed[1]=getspeed/10;//得到测到的转速的高位
disled[2]=led[mspeed[0]];//显示测速值的低位
disled[3]=led[mspeed[1]];//显示测速值的高位
PortWriteByte(0x283,0x50); //设置8253工作方式,定时器1工作方式0
PortWriteByte(0x281,0x0a); //设置定时器1的初始计数值200,低位为c8,定时1s
PortWriteByte(0x283,0xb0); //设置8253工作方式,定时器2工作方式0,(计脉冲的个数)
PortWriteByte(0x282,0xff); //设置定时器2的初始计数值ffff,低位为ff
PortWriteByte(0x282,0xff); //设置定时器2的初始计数值ffff,高位为ff
PortWriteByte(0x28b,0x0f); //初始状态时,PC7,393清零端置1,
PortWriteByte(0x28b,0x0c); //初始状态时,PC6,393计数端置0,
}
//电机转动函数模块,由void key()调用
void motorstart()
{
int pulse=0;
pulse=d*128/48;
if(pulse>128)
{
PortWriteByte(0x290,0xff); /*D/A 输出*/
}
else
{
pulse=0x80+pulse;
PortWriteByte(0x290,pulse); /*D/A 输出*/
}
}
//测量电机的转速,由void key()调用
void measurespeed()
{
}
//pid调速算法
void pidadapt()
{
int R=0;int es=0;int es1=0;int es2=0;
int es3=0;int es4=0;int es5=0;int es6=0;int es7=0;
int es8=0;int es9=0;int es10=0;int ies=0;int des=0;
int M=0;
int e1=0; int S=0;
es10=es9; //(以下是PID控制算法)
es9=es8;
es8=es7;
es7=es6;
es6=es5;
es5=es4;
es4=es3;
es3=es2;
es2=es1;
es1=es;
es=R-getspeed;
ies=1*(es+es1+es2+es3+es4+es5+es6+es7+es8+es9+es10);
des=es1-es2;
M=int (es+0.1*des+0.0001*ies);
motorstart();//电机开始转动
e1=e1+M;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -