📄 main.asm
字号:
//step motor driver //
//A0--黄线,A1--茶线,A2--绿线,A3--青线,A4完成开关次数后的指示灯//
//功能:实现步进电机以90度角正反旋转,开关9999次后亮LED灯//
//共阴极四位8段数码管//
//内部计算显示,0~9999的显示//
//A8~A15控制数值,B8~B15控制位选//
//code by ohf//
.DEFINE P_IOA_Data 0x7000;
.DEFINE P_IOA_Dir 0x7002;
.DEFINE P_IOA_Attrib 0x7003;
.DEFINE P_IOB_Data 0x7005;
.DEFINE P_IOB_Dir 0x7007;
.DEFINE P_IOB_Attrib 0x7008;
.DEFINE P_Watchdog_Clear 0x7012;
.RAM //变量单元地址段预定义
.var COUNTER_1; //定义延时外循环计数器1
.var COUNTER_2; //定义延时内循环计数器2
.var COUNTER_3; //显示时间延时参数
.var COUNTER1; //定义延时外循环计数器1
.var COUNTER2; //定义延时外循环计数器2
.var angle; //旋转角度
.Var display_number; //显示的数值,即开关的次数
.var qian_ADDRESS; //千位地址变量
.var bai_ADDRESS; //百位地址变量
.var shi_ADDRESS; //十位地址变量
.var ge_ADDRESS; //个位地址变量
.DATA
LED_ADDRESS: .DW 0xB700,0x0600,0x7300,0x5700,0xC600,0xD500,0xF500,0x0700,0xF700,0xD700; //'0''1''2''3''4''5''6''7''8''9'的代码,接A口
LED_dig: .DW 0x0100,0x0200,0x0400,0x0800; //'个位','十位','百位','千位'代码,接B口
step_code: .DW 0x0001,0x0003,0x0002,0x0006,0x0004,0x000C,0x0008,0x0009 //每步的代码,CCW
step_code1: .DW 0x0009,0x0008,0x000c,0x0004,0x0006,0x0002,0x0003,0x0001 //每步的代码,CW
.CODE //主程序单元地址段预定义
.PUBLIC _main; //定义主程序
_main:
call io_int; //IO口初始化,A与B口都为低电平输出口
R2=0;
[display_number]=R2; //开关次数初始为零
Loop_main:
R2=0x0096; //设置旋转角90度
call step_rotor_CCW; //CCW转动90度
R2=0x0096; //设置旋转角90度
call step_rotor_CW; //CW转动90度
R2=[display_number]; //开关次数显示数值加一
R2+=1;
[display_number]=R2;
call kaiguan_disp; //显示开关次数
R2=[display_number];
cmp R2,9999;
JAE Loop_stop; //大于或等于9999,则停止运行
JMP Loop_main; //小于9999,继续循环开关
Loop_stop:
call kaiguan_disp; //显示开关次数
jmp Loop_stop; //停止开关,循环显示次数
kaiguan_disp:.proc //开关次数显示
R1=0x002F; //延时参数
[COUNTER_3]=R1;
display_loop_1:
call display; //数值显示
R1=[COUNTER_3]
R1-=0x0001;
[COUNTER_3]=R1;
JNZ display_loop_1;
RETF; //子程序返回
.endp
io_int: .proc //程序初始化
R1=0xFFFF; //设定IOA0口为带数据缓存器的输出口
[P_IOA_Dir]=R1;
[P_IOA_Attrib]=R1;
[P_IOB_Dir]=R1;
[P_IOB_Attrib]=R1;
R1=0x0000;
[P_IOA_Data]=R1; //IOA0初始化 低电平输出
[P_IOB_Data]=R1; //IOA0初始化 低电平输出
RETF; //子程序返回
.endp
step_rotor_CCW: .proc //CCW转向子程序
main_loop:
[angle]=R2; //旋转角度
BP=step_code; //送CCW步进代码
ccw_loop:
R1=[BP];
[P_IOA_Data]=R1; //步进代码送输出口
CALL DELAY; //调用延时子程序0.01秒
BP=BP+1; //下一步代码
cmp R1,0x0009; //判断是否完成一周
jne ccw_loop; //没完成跳转下一步
R2=[angle]
R2-=1;
cmp R2,0x0000; //判断是否完成旋转角度
jne main_loop; //未完成旋转角度则继续执行
R1=0x0000;
[P_IOA_Data]=R1; //电机停止转动1秒
CALL DELAY1; //调用延时子程序1秒
CALL DELAY1; //调用延时子程序1秒
RETF; //子程序返回
.endp
step_rotor_CW: .proc //CCW转向子程序
main_loop1:
[angle]=R2;
BP=step_code1; //送步进代码首地址
cw_loop:
R1=[BP];
[P_IOA_Data]=R1; //步进代码送输出口
CALL DELAY; //调用延时子程序0.01秒
BP=BP+1; //下一步代码
cmp R1,0x0001; //判断是否完成一周
jne cw_loop; //没完成跳转下一步
R2=[angle]
R2-=1;
cmp R2,0x0000; //判断是否完成旋转角度
jne main_loop1; //未已完成继续循环
R1=0x0000;
[P_IOA_Data]=R1; //电机停止转动1秒
RETF; //子程序返回
.endp
display: .PROC; //显示子程序定义
//BCD转换//
R1=0x0001;
[P_Watchdog_Clear]=R1; //清狗
R2=0; //地址清零,
[qian_ADDRESS]=R2; //千位
[bai_ADDRESS]=R2; //百位
[shi_ADDRESS]=R2; //十位
[ge_ADDRESS]=R2; //个位
R1=[display_number];
cmp R1,1000; //与1000比较
jb L_baiwei; //小于1000转跳
L_qianwei:
R1-=1000; //若大于或等于则减1000
R2=[qian_ADDRESS]; //千位变量值加一
R2+=1;
[qian_ADDRESS]=R2;
cmp R1,1000; //与1000比较
JAE L_qianwei; //若大于或等于1000则跳转L_qianwei
L_baiwei:
cmp R1,100; //与100比较
jb L_shiwei; //小于100转跳L_shiwei
R1-=100; //若大于或等于100则减100
R2=[bai_ADDRESS]; //百位变量值加一
R2+=1;
[bai_ADDRESS]=R2;
cmp R1,100; //与100比较
JAE L_baiwei; //若大于或等于100则跳转L_baiwei
L_shiwei:
cmp R1,10; //与10比较
jb L_gewei; //小于10转跳L_gewei
R1-=10; //若大于或等于10则减10
R2=[shi_ADDRESS]; //十位变量值加一
R2+=1;
[shi_ADDRESS]=R2;
cmp R1,10; //与10比较
JAE L_shiwei; //若大于或等于10则跳转L_shiwei
L_gewei:
[ge_ADDRESS]=R1;
//显示//
R4=0x0800;
[P_IOB_Data]=R4; //千位位选
BP=LED_ADDRESS;
BP+=[qian_ADDRESS];
R4=[BP];
[P_IOA_Data]=R4; //千位数数选
call L_DELAY; //延时
R4=0x0400;
[P_IOB_Data]=R4; //百位位选
BP=LED_ADDRESS;
BP+=[bai_ADDRESS];
R4=[BP];
[P_IOA_Data]=R4; //百位数选
call L_DELAY; //延时
R4=0x0200;
[P_IOB_Data]=R4; //十位位选
BP=LED_ADDRESS;
BP+=[shi_ADDRESS];
R4=[BP];
[P_IOA_Data]=R4; //十位数选
call L_DELAY; //延时
R4=0x0100;
[P_IOB_Data]=R4; //个位位选
BP=LED_ADDRESS;
BP+=[ge_ADDRESS];
R4=[BP];
[P_IOA_Data]=R4; //十位数选
call L_DELAY; //延时
RETF; //子程序返回
.endp //延时子程序结束定义
DELAY: .proc //延时子程序起始定义 延时0.01秒
R2=0x01EF; //定义外循环计数器初值
[COUNTER1]=R2;
loop1: //循环
R2=[COUNTER1];
R2-=0x0001; //循环计数器减1
[COUNTER1]=R2;
JNZ loop1; //计数值不为零跳转LOOP1 溢出则执行下一条指令
R3=0x0001;
[P_Watchdog_Clear]=R3; //清狗
RETF; //子程序返回
.endp
DELAY1: .proc //延时子程序起始定义 延时2秒
R2=0xffff; //定义外循环计数器初值
[COUNTER2]=R2;
loop2: //循环
R2=[COUNTER2];
R2-=0x0001; //循环计数器减1
[COUNTER2]=R2;
JNZ loop2; //计数值不为零跳转LOOP1 溢出则执行下一条指令
R3=0x0001;
[P_Watchdog_Clear]=R3; //清狗
RETF; //子程序返回
.endp
L_DELAY: .proc //延时子程序起始定义 延时10豪秒
R2=0x0001; //定义外循环计数器初值
[COUNTER_1]=R2;
loop_1: //外循环
R2=0xFD6A; //定义内循环计数器初值
[COUNTER_2]=R2;
loop_2: //内循环 内循环结束延时0.01秒
R2=0x0001;
[P_Watchdog_Clear]=R2; //清狗
R2=[COUNTER_2];
R2+=0x0001; //内循环计数器加1
[COUNTER_2]=R2;
JNZ loop_2; //计数值不为零跳转loop_2 溢出则执行下一条指令
R2=[COUNTER_1];
R2-=0x0001; //外循环计数器减1
[COUNTER_1]=R2;
JNZ loop_1; //计数值不为零跳转loop_1 溢出则执行下一条指令
RETF; //子程序返回
.endp //延时子程序结束定义
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -