步进电机控制程序
(2008-06-05 19:07:55)
转载
标签: 分类: 程序设计
it
步进电机(键盘控制可调速)
#include
#define uchar unsigned char
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void ddelay(void); //键盘扫描延时函数
void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒
void gorun(); //步进电机控制步进函数
sbit P10=P2^0 ; //电机端口定义
sbit P11=P2^1 ;
sbit P12=P2^2;
sbit P13=P2^3 ;
void ddelay(void)
{
uchar i;
for (i=300;i>0;i--);
}
uchar keyscan(void)
{
uchar scancode;
uchar tmpcode;
P1 = 0xf8; // 发全0行扫描码
if ((P1&0xf8)!=0xf8) // 若有键按下
{
ddelay(); // 延时去抖动
if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while((scancode&0x08)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf8)!=0xf8) // 本行有键按下
tmpcode = (P1&0xf8)|0x07;
return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列
}
else scancode = (scancode
}
}
}
return(0); // 无键按下,返回值为0
}
void main(void)
{
uchar key;
count = 0;
step_index = 0;
spcount = 0;
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFc;
TL0 = 0x18; //设定时每隔1ms中断一次
TR0 = 1; //开始计数
stop_flag = 0;
turn=0;
speedlevel = 20;
while(1)
{
key = keyscan();
switch(key)
{
case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn = 0;
speedlevel =10;
gorun();
delay(1000);
break;
case 0x0c: //按键*, 停止 2000*0.5MS=0.5S
stop_flag=1;
break;
case 0x0a: //按键0, 反转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn=1;
speedlevel =10;
gorun();
delay(1000);
break;
case 0x11: // 按键9, 以--speedlevel的加速转1000*0.5MS=0.5S
stop_flag=0;
if (speedlevel==1)
{ speedlevel=1;}
else { --speedlevel;}
gorun();
delay(1000);
break;
case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5S
stop_flag=0;
++speedlevel;
gorun();
delay(1000);
break;
}
}
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFc;
TL0=0x18; //设定时每隔1ms中断一次
count++;
spcount--;
if(spcount
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒
{
count=0;
do{}
while(count
void gorun()
{
if (stop_flag==1)
{
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
return;
}
switch(step_index)
{
case 0: //0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 0;
break;
case 1: //0、1
P10 = 1;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 2: //1
P10 = 0;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 3: //1、2
P10 = 0;
P11 = 1;
P12 = 1;
P13 = 0;
break;
case 4: //2
P10 = 0;
P11 = 0;
P12 = 1;
P13 = 0;
break;
case 5: //2、3
P10 = 0;
P11 = 0;
P12 = 1;
P13 = 1;
break;
case 6: //3
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 1;
break;
case 7: //3、0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 1;
}
if (turn==0) //正转
{
step_index++;
if (step_index>7)
step_index=0;
}
else
{ //反转
step_index--;
if (step_index
step_index=7;
}
}
步进电机(键盘控制可调速加显示)
#include
#define uchar unsigned char
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void ddelay(void); //键盘扫描延时函数
void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒
void gorun(); //步进电机控制步进函数
void Delay400Ms(void);
void LCMInit(void); //LCM初始化
void WriteCommandLCM(unsigned char WCLCM,BuysC); //BuysC为0时忽略忙检测 void DisplayOneChar(uchar X, uchar Y, uchar DData);
void DisplayListChar(uchar X, uchar Y,uchar ListLength, uchar *DData,uchar n);
sbit P10=P3^0 ; //电机端口定义
sbit P11=P3^1 ;
sbit P12=P3^2;
sbit P13=P3^3 ;
uchar code speed[]={ 0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30};
uchar code stop[] = {"stop"};
uchar code go[] = {"go:"};
uchar code back[] = {"back:"};
uchar code max[] = {"max:8"};
void ddelay(void)
{
uchar i;
for (i=300;i>0;i--);
}
uchar keyscan(void)
{
uchar scancode;
uchar tmpcode;
P1 = 0xf8; // 发全0行扫描码
if ((P1&0xf8)!=0xf8) // 若有键按下
{
ddelay(); // 延时去抖动
if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while((scancode&0x08)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf8)!=0xf8) // 本行有键按下
{
tmpcode = (P1&0xf8)|0x07;
return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列
}
else scancode = (scancode
}
}
}
return(0); // 无键按下,返回值为0
}
void main(void)
{
uchar key;
count = 0;
step_index = 0;
spcount = 0;
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFc;
TL0 = 0x18; //设定时每隔1ms中断一次
TR0 = 1; //开始计数
P0=0XFF;
P3 &=0XEF; //573片选
LCMInit(); //LCM初始化
Delay400Ms();
stop_flag = 0;
turn=0;
speedlevel = 5;
DisplayListChar(0,0,3,go,1); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
while(1)
{
key = keyscan();
switch(key)
{
case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn = 0;
speedlevel =5;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x0c: //按键*, 停止 2000*0.5MS=0.5S
stop_flag=1;
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,4,stop,0); //每次扫描键盘显示更新一次
break;
case 0x0a: //按键0, 反转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn=1;
speedlevel =5;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x11: // 按键9, 以--speedlevel的加速转1000*0.5MS=0.5S
stop_flag=0;
if (speedlevel==2)
{ speedlevel=2;}
else { speedlevel--;}
gorun();
if(speedlevel==2)
{ DisplayListChar(0,1,5,max,0);}
else {DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5S
stop_flag=0;
speedlevel++;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
if(turn==0)
{DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次
else {DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次
DisplayOneChar(0,1,speed[speedlevel]);} //每次扫描键盘显示更新一次
delay(1000);
break;
}
}
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFc;
TL0=0x18; //设定时每隔1ms中断一次
count++;
spcount--;
if(spcount
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒
{
count=0;
do{}
while(count
}
void gorun()
{
if (stop_flag==1)
{
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
return;
}
switch(step_index)
{
case 0: //0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 0;
break;
case 1: //0、1
P10 = 1;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 2: //1
P10 = 0;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 3: //1、2 P10 = 0;
P11 = 1;
P12 = 1;
P13 = 0;
break;
case 4: //2 P10 = 0;
P11 = 0;
P12 = 1;
P13 = 0;
break;
case 5: //2、3 P10 = 0;
P11 = 0;
P12 = 1;
P13 = 1;
break;
case 6: //3
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 1;
break;
case 7: //3、0 P10 = 1;
P11 = 0;
P12 = 0;
P13 = 1;
}
if (turn==0) //正转 {
step_index++; if (step_index>7) step_index=0; }
else
{ //反转 step_index--; if (step_index
step_index=7;
}
}
步进电机(自动循环调速)
#include
sbit P00=P2^0 ;
sbit P01=P2^1 ;
sbit P02=P2^2;
sbit P03=P2^3 ;
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越快,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void delay(unsigned int endcount); //延时函数,延时为endcount*0.5毫秒
void gorun(); //步进电机控制步进函数
void main(void)
{
count = 0;
step_index = 0;
spcount = 0;
stop_flag = 0;
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFE;
TL0 = 0x0C; //设定时每隔0.5ms中断一次
TR0 = 1; //开始计数
turn = 0;
do{
speedlevel =4;
delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1S
speedlevel =4;
delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1S
stop_flag=1;
delay(6000);//停止,2000*0.5MS=3S
stop_flag=0;
}while(1);
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFE;
TL0=0x0C; //设定时每隔0.5ms中断一次
count++;
spcount--;
if(spcount
{
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)
{
count=0;
do{}while(count
}
void gorun()
{
if (stop_flag==1)
{
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 0;
return;
}
switch(step_index)
{
case 0: //0
P00 = 1;
P01 = 0;
P02 = 0;
P03 = 0;
break;
case 1: //0、1
P00 = 1;
P01 = 1;
P02 = 0;
P03 = 0;
break;
case 2: //1
P00 = 0;
P01 = 1;
P02 = 0;
P03 = 0;
break;
case 3: //1、2
P00 = 0;
P01 = 1;
P02 = 1;
P03 = 0;
break;
case 4: //2
P00 = 0;
P01 = 0;
P02 = 1;
P03 = 0;
break;
case 5: //2、3
P00 = 0;
P01 = 0;
P02 = 1;
P03 = 1;
break;
case 6: //3
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 1;
break;
case 7: //3、0
P00 = 1;
P01 = 0;
P02 = 0;
P03 = 1;
}
if (turn==0)
{
step_index++;
if (step_index>7)
step_index=0;
}
else
{
step_index--;
if (step_index
step_index=7;
}
}
步进电机控制
Link - Thu, 17 Jan 2008 12:41:32 +0800
Description:
本设计采用的步进电机为35BYJ46型四相八拍电机,电压为DC12V。
工作原理:利用INTER 8255A对四相步进电机进行控制。当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)等。
35BYJ46步进电机为四相八拍,其相序表如下:
步序 PA3 PA2 PA1 PA0 对应A口输出值
1 0 0 0 1 01H
2 0 0 1 1 03H
3 0 0 1 0 02H
4 0 1 1 0 06H
5 0 1 0 0 04H
6 1 1 0 0 0CH
7 1 0 0 0 08H
8 1 0 0 1 09H
实验程序如下:
;FILENAME: 步进电机控制.ASM
;内容: 步进电机控制
STACK SEGMENT STACK
DW 256 DUP(?)
STACK ENDS
P55A EQU 60H ;8255A口输出
P55C EQU 62H ;8255C口输入
P55CTL EQU 63H ;8255控制口
DATA SEGMENT
BUF DB 0
MES DB 'K0-K6 ARE SPEED CONTROL', 0DH, 0AH
DB 'K6 IS THE LOWEST SPEED', 0DH, 0AH
DB 'K0 IS THE HIGHEST SPEED', 0DH, 0AH
DB 'K7 IS THE DIRECTION CONTROL', 0DH, 0AH, '$'
TABLE DB 01H,03H,02H,06H,04H,0CH,08H,09H
TABLE1 DB 01H,09H,08H,0CH,04H,06H,02H,03H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START: MOV AX, CS
MOV DS, AX
MOV AX, DATA
MOV DS, AX
MOV DX, OFFSET MES
MOV AH, 09 ; dos调用,在显示器上显示以$为结
束符的字符串,
INT 21H ; 若显示字符串要求回车换行则在其
后加入0dh,0ah。
MOV DX, P55CTL
MOV AL, 8BH ;10001011B
OUT DX, AL ;8255C输入, A输出
MOV BUF, 33H
OUT1: MOV AL, BUF
MOV DX, P55A
OUT DX, AL ;从A口输出00110011
PUSH DX
MOV AH, 06H
MOV DL, 0FFH ;DOS调用,直接控制台读写,DL=0FF 输入,DL=字符 输出;
INT 21H ;检查有无键按下
POP DX
JE IN1 ;ZF=1,则跳转
MOV AH, 4CH ;带返回码结束,AL=返回码
INT 21H
IN1: MOV DX, P55C
IN AL,DX ;读开关状态,则跳转至相应开关处
TEST AL, 01H
JNZ K0
TEST AL, 02H
JNZ K1
TEST AL, 04H
JNZ K2
TEST AL, 08H
JNZ K3
TEST AL, 10H
JNZ K4
TEST AL, 20H
JNZ K5
TEST AL, 40H
JNZ K6
STOP: MOV DX, P55A
MOV AL, 0FFH
JMP OUT1
K0: MOV BL, 10H
SAM: TEST AL, 80H ;K7是否为1,是则步进电机正转,否则反转 JZ ZX0
JMP NX0
K1: MOV BL, 18H
JMP SAM
K2: MOV BL, 20H
JMP SAM
K3: MOV BL, 40H
JMP SAM
K4: MOV BL, 80H
JMP SAM
K5: MOV BL, 0C0H
JMP SAM
K6: MOV BL, 0FFH
JMP SAM
ZX0:
MOV BX,OFFSET TABLE
MOV CX,0008H
ZX1: MOV AL,[BX]
OUT 61H,AL
CALL DELAY
INC BX
LOOP ZX1
JMP OUT1
NX0:
MOV BX,OFFSET TABLE1
MOV CX,0008H
NX1: MOV AL,[BX]
OUT 61H,AL
CALL DELAY
INC BX
LOOP NX1
JMP OUT1
DELAY PROC NEAR ;延时子程序 DELAY1:
MOV CX, 05A4H
DELAY2:
LOOP DELAY2
DEC BL
JNZ DELAY1
RET
DELAY ENDP
CODE ENDS
END START
步进电机控制程序
(2008-06-05 19:07:55)
转载
标签: 分类: 程序设计
it
步进电机(键盘控制可调速)
#include
#define uchar unsigned char
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void ddelay(void); //键盘扫描延时函数
void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒
void gorun(); //步进电机控制步进函数
sbit P10=P2^0 ; //电机端口定义
sbit P11=P2^1 ;
sbit P12=P2^2;
sbit P13=P2^3 ;
void ddelay(void)
{
uchar i;
for (i=300;i>0;i--);
}
uchar keyscan(void)
{
uchar scancode;
uchar tmpcode;
P1 = 0xf8; // 发全0行扫描码
if ((P1&0xf8)!=0xf8) // 若有键按下
{
ddelay(); // 延时去抖动
if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while((scancode&0x08)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf8)!=0xf8) // 本行有键按下
tmpcode = (P1&0xf8)|0x07;
return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列
}
else scancode = (scancode
}
}
}
return(0); // 无键按下,返回值为0
}
void main(void)
{
uchar key;
count = 0;
step_index = 0;
spcount = 0;
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFc;
TL0 = 0x18; //设定时每隔1ms中断一次
TR0 = 1; //开始计数
stop_flag = 0;
turn=0;
speedlevel = 20;
while(1)
{
key = keyscan();
switch(key)
{
case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn = 0;
speedlevel =10;
gorun();
delay(1000);
break;
case 0x0c: //按键*, 停止 2000*0.5MS=0.5S
stop_flag=1;
break;
case 0x0a: //按键0, 反转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn=1;
speedlevel =10;
gorun();
delay(1000);
break;
case 0x11: // 按键9, 以--speedlevel的加速转1000*0.5MS=0.5S
stop_flag=0;
if (speedlevel==1)
{ speedlevel=1;}
else { --speedlevel;}
gorun();
delay(1000);
break;
case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5S
stop_flag=0;
++speedlevel;
gorun();
delay(1000);
break;
}
}
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFc;
TL0=0x18; //设定时每隔1ms中断一次
count++;
spcount--;
if(spcount
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒
{
count=0;
do{}
while(count
void gorun()
{
if (stop_flag==1)
{
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
return;
}
switch(step_index)
{
case 0: //0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 0;
break;
case 1: //0、1
P10 = 1;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 2: //1
P10 = 0;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 3: //1、2
P10 = 0;
P11 = 1;
P12 = 1;
P13 = 0;
break;
case 4: //2
P10 = 0;
P11 = 0;
P12 = 1;
P13 = 0;
break;
case 5: //2、3
P10 = 0;
P11 = 0;
P12 = 1;
P13 = 1;
break;
case 6: //3
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 1;
break;
case 7: //3、0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 1;
}
if (turn==0) //正转
{
step_index++;
if (step_index>7)
step_index=0;
}
else
{ //反转
step_index--;
if (step_index
step_index=7;
}
}
步进电机(键盘控制可调速加显示)
#include
#define uchar unsigned char
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void ddelay(void); //键盘扫描延时函数
void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒
void gorun(); //步进电机控制步进函数
void Delay400Ms(void);
void LCMInit(void); //LCM初始化
void WriteCommandLCM(unsigned char WCLCM,BuysC); //BuysC为0时忽略忙检测 void DisplayOneChar(uchar X, uchar Y, uchar DData);
void DisplayListChar(uchar X, uchar Y,uchar ListLength, uchar *DData,uchar n);
sbit P10=P3^0 ; //电机端口定义
sbit P11=P3^1 ;
sbit P12=P3^2;
sbit P13=P3^3 ;
uchar code speed[]={ 0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30};
uchar code stop[] = {"stop"};
uchar code go[] = {"go:"};
uchar code back[] = {"back:"};
uchar code max[] = {"max:8"};
void ddelay(void)
{
uchar i;
for (i=300;i>0;i--);
}
uchar keyscan(void)
{
uchar scancode;
uchar tmpcode;
P1 = 0xf8; // 发全0行扫描码
if ((P1&0xf8)!=0xf8) // 若有键按下
{
ddelay(); // 延时去抖动
if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while((scancode&0x08)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf8)!=0xf8) // 本行有键按下
{
tmpcode = (P1&0xf8)|0x07;
return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列
}
else scancode = (scancode
}
}
}
return(0); // 无键按下,返回值为0
}
void main(void)
{
uchar key;
count = 0;
step_index = 0;
spcount = 0;
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFc;
TL0 = 0x18; //设定时每隔1ms中断一次
TR0 = 1; //开始计数
P0=0XFF;
P3 &=0XEF; //573片选
LCMInit(); //LCM初始化
Delay400Ms();
stop_flag = 0;
turn=0;
speedlevel = 5;
DisplayListChar(0,0,3,go,1); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
while(1)
{
key = keyscan();
switch(key)
{
case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn = 0;
speedlevel =5;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x0c: //按键*, 停止 2000*0.5MS=0.5S
stop_flag=1;
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,4,stop,0); //每次扫描键盘显示更新一次
break;
case 0x0a: //按键0, 反转以speedlevel = 1的速度转1000*0.5MS=0.5S
stop_flag=0;
turn=1;
speedlevel =5;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次
DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x11: // 按键9, 以--speedlevel的加速转1000*0.5MS=0.5S
stop_flag=0;
if (speedlevel==2)
{ speedlevel=2;}
else { speedlevel--;}
gorun();
if(speedlevel==2)
{ DisplayListChar(0,1,5,max,0);}
else {DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次
delay(1000);
break;
case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5S
stop_flag=0;
speedlevel++;
gorun();
WriteCommandLCM(0x01,1);//显示清屏,
if(turn==0)
{DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[]
DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次
else {DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次
DisplayOneChar(0,1,speed[speedlevel]);} //每次扫描键盘显示更新一次
delay(1000);
break;
}
}
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFc;
TL0=0x18; //设定时每隔1ms中断一次
count++;
spcount--;
if(spcount
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒
{
count=0;
do{}
while(count
}
void gorun()
{
if (stop_flag==1)
{
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 0;
return;
}
switch(step_index)
{
case 0: //0
P10 = 1;
P11 = 0;
P12 = 0;
P13 = 0;
break;
case 1: //0、1
P10 = 1;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 2: //1
P10 = 0;
P11 = 1;
P12 = 0;
P13 = 0;
break;
case 3: //1、2 P10 = 0;
P11 = 1;
P12 = 1;
P13 = 0;
break;
case 4: //2 P10 = 0;
P11 = 0;
P12 = 1;
P13 = 0;
break;
case 5: //2、3 P10 = 0;
P11 = 0;
P12 = 1;
P13 = 1;
break;
case 6: //3
P10 = 0;
P11 = 0;
P12 = 0;
P13 = 1;
break;
case 7: //3、0 P10 = 1;
P11 = 0;
P12 = 0;
P13 = 1;
}
if (turn==0) //正转 {
step_index++; if (step_index>7) step_index=0; }
else
{ //反转 step_index--; if (step_index
step_index=7;
}
}
步进电机(自动循环调速)
#include
sbit P00=P2^0 ;
sbit P01=P2^1 ;
sbit P02=P2^2;
sbit P03=P2^3 ;
static unsigned int count; //计数
static int step_index; //步进索引数,值为0-7
static bit turn; //步进电机转动方向
static bit stop_flag; //步进电机停止标志
static int speedlevel; //步进电机转速参数,数值越大速度越快,最小值为1,速度最慢 static int spcount; //步进电机转速参数计数
void delay(unsigned int endcount); //延时函数,延时为endcount*0.5毫秒
void gorun(); //步进电机控制步进函数
void main(void)
{
count = 0;
step_index = 0;
spcount = 0;
stop_flag = 0;
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFE;
TL0 = 0x0C; //设定时每隔0.5ms中断一次
TR0 = 1; //开始计数
turn = 0;
do{
speedlevel =4;
delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1S
speedlevel =4;
delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1S
stop_flag=1;
delay(6000);//停止,2000*0.5MS=3S
stop_flag=0;
}while(1);
}
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFE;
TL0=0x0C; //设定时每隔0.5ms中断一次
count++;
spcount--;
if(spcount
{
spcount = speedlevel;
gorun();
}
}
void delay(unsigned int endcount)
{
count=0;
do{}while(count
}
void gorun()
{
if (stop_flag==1)
{
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 0;
return;
}
switch(step_index)
{
case 0: //0
P00 = 1;
P01 = 0;
P02 = 0;
P03 = 0;
break;
case 1: //0、1
P00 = 1;
P01 = 1;
P02 = 0;
P03 = 0;
break;
case 2: //1
P00 = 0;
P01 = 1;
P02 = 0;
P03 = 0;
break;
case 3: //1、2
P00 = 0;
P01 = 1;
P02 = 1;
P03 = 0;
break;
case 4: //2
P00 = 0;
P01 = 0;
P02 = 1;
P03 = 0;
break;
case 5: //2、3
P00 = 0;
P01 = 0;
P02 = 1;
P03 = 1;
break;
case 6: //3
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 1;
break;
case 7: //3、0
P00 = 1;
P01 = 0;
P02 = 0;
P03 = 1;
}
if (turn==0)
{
step_index++;
if (step_index>7)
step_index=0;
}
else
{
step_index--;
if (step_index
step_index=7;
}
}
步进电机控制
Link - Thu, 17 Jan 2008 12:41:32 +0800
Description:
本设计采用的步进电机为35BYJ46型四相八拍电机,电压为DC12V。
工作原理:利用INTER 8255A对四相步进电机进行控制。当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)等。
35BYJ46步进电机为四相八拍,其相序表如下:
步序 PA3 PA2 PA1 PA0 对应A口输出值
1 0 0 0 1 01H
2 0 0 1 1 03H
3 0 0 1 0 02H
4 0 1 1 0 06H
5 0 1 0 0 04H
6 1 1 0 0 0CH
7 1 0 0 0 08H
8 1 0 0 1 09H
实验程序如下:
;FILENAME: 步进电机控制.ASM
;内容: 步进电机控制
STACK SEGMENT STACK
DW 256 DUP(?)
STACK ENDS
P55A EQU 60H ;8255A口输出
P55C EQU 62H ;8255C口输入
P55CTL EQU 63H ;8255控制口
DATA SEGMENT
BUF DB 0
MES DB 'K0-K6 ARE SPEED CONTROL', 0DH, 0AH
DB 'K6 IS THE LOWEST SPEED', 0DH, 0AH
DB 'K0 IS THE HIGHEST SPEED', 0DH, 0AH
DB 'K7 IS THE DIRECTION CONTROL', 0DH, 0AH, '$'
TABLE DB 01H,03H,02H,06H,04H,0CH,08H,09H
TABLE1 DB 01H,09H,08H,0CH,04H,06H,02H,03H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START: MOV AX, CS
MOV DS, AX
MOV AX, DATA
MOV DS, AX
MOV DX, OFFSET MES
MOV AH, 09 ; dos调用,在显示器上显示以$为结
束符的字符串,
INT 21H ; 若显示字符串要求回车换行则在其
后加入0dh,0ah。
MOV DX, P55CTL
MOV AL, 8BH ;10001011B
OUT DX, AL ;8255C输入, A输出
MOV BUF, 33H
OUT1: MOV AL, BUF
MOV DX, P55A
OUT DX, AL ;从A口输出00110011
PUSH DX
MOV AH, 06H
MOV DL, 0FFH ;DOS调用,直接控制台读写,DL=0FF 输入,DL=字符 输出;
INT 21H ;检查有无键按下
POP DX
JE IN1 ;ZF=1,则跳转
MOV AH, 4CH ;带返回码结束,AL=返回码
INT 21H
IN1: MOV DX, P55C
IN AL,DX ;读开关状态,则跳转至相应开关处
TEST AL, 01H
JNZ K0
TEST AL, 02H
JNZ K1
TEST AL, 04H
JNZ K2
TEST AL, 08H
JNZ K3
TEST AL, 10H
JNZ K4
TEST AL, 20H
JNZ K5
TEST AL, 40H
JNZ K6
STOP: MOV DX, P55A
MOV AL, 0FFH
JMP OUT1
K0: MOV BL, 10H
SAM: TEST AL, 80H ;K7是否为1,是则步进电机正转,否则反转 JZ ZX0
JMP NX0
K1: MOV BL, 18H
JMP SAM
K2: MOV BL, 20H
JMP SAM
K3: MOV BL, 40H
JMP SAM
K4: MOV BL, 80H
JMP SAM
K5: MOV BL, 0C0H
JMP SAM
K6: MOV BL, 0FFH
JMP SAM
ZX0:
MOV BX,OFFSET TABLE
MOV CX,0008H
ZX1: MOV AL,[BX]
OUT 61H,AL
CALL DELAY
INC BX
LOOP ZX1
JMP OUT1
NX0:
MOV BX,OFFSET TABLE1
MOV CX,0008H
NX1: MOV AL,[BX]
OUT 61H,AL
CALL DELAY
INC BX
LOOP NX1
JMP OUT1
DELAY PROC NEAR ;延时子程序 DELAY1:
MOV CX, 05A4H
DELAY2:
LOOP DELAY2
DEC BL
JNZ DELAY1
RET
DELAY ENDP
CODE ENDS
END START