Proteus电梯课设

编程入门 行业动态 更新时间:2024-10-07 19:20:59

Proteus<a href=https://www.elefans.com/category/jswz/34/1762102.html style=电梯课设"/>

Proteus电梯课设

通过Proteus实现8层楼电梯:
8层楼的电梯,
可以实现内部和外部的按键的功能,
以及通过的算法实现楼层的选择。
有数码管显示和lcd显示,
以及到达楼层后的铃声提示。

具体实现见代码注释:

DATAS SEGMENT;此处输入数据段代码IOY0 equ 0E000hIOY1 equ 0E040hIOY2 equ 0E080hIOY3 equ 0E0C0hIOY4 equ 0E100hFirst_A equ IOY0+00H*4First_B equ IOY0+01H*4First_C equ IOY0+02H*4First_MODE equ IOY0+03H*4Seq db 20 dup(?);记录按下的三个序号Ordered db 20 dup(?);记录下排序之后的seq数组ordered_num db 00hnum db 0LED db 01h,02h,04h,08h,10h,20h,40h,80h;点亮对应的部分Out_LED db 0feh,0fdh,0fbh,0f7h,0efh,0dfh,0bfh,7fh;熄灭对应的部分Current_LED db ?Row_disp db 0feh,0fdh,0fbh,0f7hStop_flag db 00h;停止标志Stop_mode db 00h;存储当前的停止运行标志;-------------------------------------------Second_A equ IOY1+00h*2Second_B equ IOY1+01h*2Second_C equ IOY1+02h*2Second_MODE equ IOY1+03h*2buf1 db 'Welcome'length1 db $-buf1buf2 db 'Up'length2 db $-buf2buf3 db 'Down'length3 db $-buf3buf4 db 'Close'length4 db $-buf4buf5 db 'Open'length5 db $-buf5buf6 db 'Run'length6 db $-buf6buf7 db 4 dup(' ')length7 db $-buf7Row db ?Line db ?;----------------------------------MY8253_COUNT0 equ IOY2+00H*4MY8253_COUNT1 equ IOY2+01H*4MY8253_COUNT2 equ IOY2+02H*4MY8253_MODE equ IOY2+03H*4;----------------------------------current_floor db 01h;当前楼层aim_floor db ?;输入的目标楼层;----------------------------------Third_A equ IOY3+00h*2Third_B equ IOY3+01h*2Third_C equ IOY3+02h*2Third_Mode equ IOY3+03h*3;----------------------------------TFREQ dw 264,264,396,396,0TDLY dw 6000,6000,6000,6000;----------------------------------Fourth_A equ IOY4+00h*4Fourth_B equ IOY4+01h*4Fourth_C equ IOY4+02h*4Fourth_Mode equ IOY4+03h*4Outside db 20 dup(?);外部输入楼层Out_num db 00hCurrent_up_led db 00hCurrent_down_led db 00hCurrent_dir db 01h;00h表示下行,01h表示上行;----------------------------------max db ?;放入当前数据的最大值dir db ?;表示运行的方向,1是上行,0是下行sort_dir db ?;表示冒泡排序的方向,0表示正向排序,1表示反向排序tmp db 20 dup(?);用于暂存的数据tmp_num db 00h
DATAS ENDSSTACKS SEGMENT;此处输入堆栈段代码dw 50 dup(?)top label byte
STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATAS,SS:STACKS
START:mov ax,stacksmov ss,axmov sp,offset topMOV AX,DATASMOV DS,AX;此处输入代码段代码;call Lcd_main;call Running;初始化当前楼层显示1mov dx,Third_modemov al,10000010B;A口输出,B口输入,C口第四位输出out dx,al;设置当前8255的模式mov al,current_floormov dx,Third_Aout dx,al;------------------------------------;设置外部键盘8255的模式mov dx,Fourth_Mode mov al,10001000B;A,B都为输出信号,C的高位为输入信号,D的高位为输出信号out dx,alcall Lcd_main
Again:call keyboardjmp again
;-------------------------------------
Keyboard proc nearmov al,10001000B;A为输出信号,C的高位为输入信号列,低位为输出信号行mov dx,First_modeout dx,almov bh,00h;从第零行开始扫描mov bl,00h
Restart:call disp
Detect_row:mov dx,First_Cmov al,row_disp[bx]out dx,alin al,dxand al,0f0hcmp al,0f0hjnc next_line;无输入直接转到下一行mov cx,4000hloop $in al,dxand al,0f0hcmp al,0f0hjnc next_linemov dl,0;用于记录该行中列的数据mov cx,4
Find_line:shl al,1jnc record_line;无进位说明是列inc dlloop Find_line
Record_line:mov al,bl;行的数据保存在bl中,列的数据保存在dl中shl al,1shl al,1mov dh,03hsub dh,dladd al,dhcall xiaodou;记录之后继续扫描下一行
Next_line:call delayadd bl,01h;test bl,04h;jz Detect_row;没有扫描完继续扫描下一行and bl,0fbhjmp restart
Stop:ret
Keyboard endpXiaodou proc near;判断两次输入的seq是否相同,相同只当一次push dxpush bxmov bh,00hmov bl,num;bl表示序号,al表示输入的键值cmp al,07h;输入键的范围超过数字键的范围ja function;输入的可能是功能键也可能是无效键cmp bl,01h;至少当al为01的时候才有比较的意义jae comparejmp save;num为00h进入保存阶段
;----------------------------------------------
compare:;需要看这次输入的数据以前是否输入过;dec bl;上一次的数据;mov dl,seq[bx];上一次的数据存储在dl中,seq的末尾;cmp dl,al;这一次的数据存储在al中;je stop1;如果相等退出,不记录这一次的结果;cmp bl,01h;如果bl大于等于02h说明超范围了;ja lights_out ;inc blmov cl,almov ch,00hmov ah,01hcmp cx,00hja loop_com;如果是0的话不能进入左移jmp end_com
Loop_com:shl ah,01hloop loop_com
End_com:mov dl,current_ledtest dl,ahjnz stop1cmp bl,02hja lights_out
;----------------------------------------------
save:mov seq[bx],al;将数据记录到seq中去inc num;num的数值自增1,当num的数值大于3时,自动清零jmp stop1
lights_out:mov num,00hmov al,00h;这里不应该只对应显示功能在后面的停止电梯中页应该用到mov dx,First_A out dx,aljmp stop1
Function:cmp al,0bh;超出范围表示无效ja stop1cmp al,08h;启动键je Run_elecmp al,09h;紧急停止键je Stop_elecmp al,0ah;求助键je Help_elecmp al,0bh;进入外部按键的选择je Out_ele
Run_ele:;启动将数据从seq中装入aim_floor,显示close;应该要分成三种情况;第一种当前楼层在输入的楼层之间,默认先上行;第二种情况是当前楼层比输入的楼层低;第三种情况是当前楼层比输入的楼层高;第四种情况无输入楼层;输入完成之后要将已经到达的楼层从seq中清除出去call process;ordered存储的是排好序的数据cmp ordered_num,00h;首先要排除没有输入的情况je stop1;-------------------------------------------;运行部分mov cl,ordered_num;循环次数为元素的个数mov ch,00hlea bx,ordered;-------------------------------------------;测试处理的结果;mov bx,01h;mov al,ordered[bx];call show_number;jmp $;经过测试ordered中的数据正确;-------------------------------------------
Loop_running:;意思是seq中的每一层都去mov al,[bx];seq中的最后一个数据应该先去inc al;真实层数应该加1mov aim_floor,alcall Running;运行程序;-------------------------------------------mov row,01hmov line,04hlea di,buf4;显示'Close',在关门的时候显示push cxmov cl,length4call show_stringpop cxcall Wait_5s;-------------------------------------------;清除部分,熄灭对应数码管,从seq中清除,num自减1mov dh,00hmov dl,[bx]mov si,dx;---------------------------------------------;熄灭主程序部分程序mov ah,current_led;将当前的led显示放入ah中mov al,Out_led[si];将熄灭数据放入al中and al,ah;熄灭后的新输出mov dx,First_Aout dx,almov current_led,al;输入新的输出数据;---------------------------------------------;在程序里剥离了方向关系,可是这里其实是有方向关系的;有方向和楼层;---------------------------------------------;mov al,current_dir;cmp al,00h;00h为下行,01h为上行,还没有解决的问题是同时有上有下即重复的情况,转场的情况;je Down_out;jmp up_out;-------------------------------------------------cmp cx,01h;只剩下最后一个楼层的情况je loop_endmov dl,[bx]mov dh,[bx+1]cmp dl,dhjbe up_pro;这一个时刻比下一个时刻小是上行jmp down_pro
Up_pro:mov al,01h;01h为上行mov ah,current_dirxor al,ah;如果异或的结果相同说明是上行cmp al,00hje up_outjmp both_out
Down_pro:mov al,00h;00h为下行mov ah,current_dirxor al,ah;如果异或的结果相同说明为下行cmp al,00hje down_outjmp both_out;-------------------------------------------------
Down_out:mov ah,current_down_ledmov al,out_led[si]and al,ahmov dx,Fourth_Bout dx,almov current_down_led,aljmp out_end
Up_out:mov ah,current_up_ledmov al,out_led[si]and al,ahmov dx,Fourth_Aout dx,almov current_up_led,aljmp out_end
;------------------------------------------
Both_out:mov ah,current_down_ledmov al,out_led[si]and al,ahmov dx,Fourth_Bout dx,almov current_down_led,al;--------------------------mov ah,current_up_ledmov al,out_led[si]and al,ahmov dx,Fourth_Aout dx,almov current_up_led,al
;------------------------------------------
Out_end:inc bx;bx自增1;--------------------------------------;模拟cx语句dec cxcmp cx,00hjne loop_running;--------------------------------------;loop Loop_running
loop_end:mov num,00hmov ordered_num,00hmov out_num,00h;熄灭外部中的所有灯mov al,00hmov dx,Fourth_Aout dx,almov dx,Fourth_Bout dx,almov current_up_led,almov current_down_led,aljmp stop1
Stop_ele:;停止中断runningcall stop_runningjmp stop1
Help_ele:;求助,这个用在串口通信中jmp stop1
Out_ele:call keyboard2
stop1:pop bxpop dxret
Xiaodou endp
;-----------------------------------------
;键盘2的相关函数
Keyboard2 proc nearmov dx,Fourth_Amov al,00hout dx,almov dx,Fourth_Bmov al,00hout dx,almov bx,00h;从第零行开始扫描
Restart:
Detect_row:mov dx,Fourth_Cmov al,row_disp[bx]out dx,alin al,dxand al,0f0hcmp al,0f0hjnc next_line;无输入直接转到下一行mov cx,5000hloop $in al,dxand al,0f0hcmp al,0f0hjnc next_linemov dl,0;用于记录该行中列的数据mov cx,4
Find_line:shl al,1jnc record_line;无进位说明是列inc dlloop Find_line
Record_line:mov al,bl;行的数据保存在bl中,列的数据保存在dl中shl al,1shl al,1mov dh,03hsub dh,dladd al,dhcmp al,07h;如果按下了功能键返回主键盘je return_keycall Xiaodou2;al中的值没有改变call disp2;使用al中的值;记录之后继续扫描下一行
Next_line:call delayadd bl,01hand bl,0fbhjmp restartret
Return_key:;返回主键盘部分ret
Keyboard2 endpXiaodou2 proc near;判断两次输入的seq是否相同,相同只当一次push dxpush bxmov bh,00hmov bl,out_numcmp bl,01h;至少当al为01的时候才有比较的意义jae comparecmp bl,0fhja lights_outjmp save;num为00h进入保存阶段
;-------------------------------------------
compare:;dec bl;上一次的数据;mov dl,Outside[bx];上一次的数据存储在dl中,seq的末尾;cmp dl,al;这一次的数据存储在al中;je stop1;如果相等退出,不记录这一次的结果 ;inc blcmp al,07hja big_com
Small_com:mov cl,almov ch,00hmov ah,01hcmp cx,00hja loop_com1;如果是0的话不能进入左移jmp end_com1
Loop_com1:shl ah,01hloop loop_com1
End_com1:mov dl,current_up_ledtest dl,ahjnz stop1jmp save
Big_com:mov cl,alsub cl,08hmov ch,00hmov ah,01hcmp cx,00hja loop_com2;如果是0的话不能进入左移jmp end_com2
Loop_com2:shl ah,01hloop loop_com2
End_com2:mov dl,current_down_ledtest dl,ahjnz stop1
;-------------------------------------------
save:mov Outside[bx],al;将数据记录到seq中去inc out_num;out_num的数值自增1jmp stop1
lights_out:mov Out_num,00hmov al,00h;这里不应该只对应显示功能在后面的停止电梯中页应该用到mov dx,Fourth_A out dx,almov dx,Fourth_Bout dx,aljmp stop1
stop1:pop bxpop dxret
Xiaodou2 endpDisp2 proc near;数码管显示部分push bxcmp al,08h;将al和08h进行比较jb up;up范围为00-07jmp down;down范围为08-0f
Up:mov bl,almov bh,00hmov al,LED[bx]mov ah,current_up_ledor al,ahmov current_up_led,al;更新上升数据mov dx,Fourth_Aout dx,aljmp stop1
Down:sub al,08hmov bl,almov bh,00hmov al,LED[bx]mov ah,current_down_ledor al,ahmov current_down_led,al;更新上升数据mov dx,Fourth_Bout dx,al
Stop1:pop bxret
Disp2 endp
;--------------------------------------------------
Stop_running proc near;这里要使用中断不然不能不能使用mov num,00hmov out_num,00hmov ordered_num,00hmov al,00h;这里不应该只对应显示功能在后面的停止电梯中页应该用到mov dx,First_Aout dx,almov dx,Fourth_Aout dx,almov dx,Fourth_Bout dx,almov current_led,almov current_up_led,almov current_down_led,alret
stop_running endpWait_5s proc near;软件延时程序push cxpush axmov cx,0ffh
D1:mov ax,0fffh
D2:dec axjnz d2loop d1pop axpop cxret
Wait_5s endp
;-------------------------------------------------------
Process proc near;分四种情况,改变seq中数据存放的顺序push axpush bxpush cxpush dx
;-----------------------------------------------
Next_pro:;显示原始数据
;-----------------------------------------------;先对其进行正序排序;--------------------------------------lea di,seqmov cl,num;cx为比较轮数,大循环次数mov ch,00hmov sort_dir,00h;选择正向排序call bubble;--------------------------------------lea di,outsidemov cl,out_num;cx为比较轮数,大循环次数mov sort_dir,00h;选择正向排序call Bubble  
;-----------------------------------------------
;判断最大值部分
;还有一种情况内部没有按键的情况根据外面的按键确定也是上优先于下mov bl,nummov bh,00hcmp bx,00hje find_out_maxdec bxmov al,seq[bx]mov max,aljmp max_dir
Find_out_max:;分成两部分一部分是上行楼层的最大值,一部分是下行楼层的最大值mov bl,out_nummov bh,00hcmp bx,00h;两个数组都为0,直接结束je end_prodec bx;---------------------------------------------;ah中保存下行楼层的最大值mov ah,outside[bx];最后一个元素不一定是下行的最大值,比如没有下行的情况就是上行的最大值cmp ah,09hjb down_maxsub ah,08h;---------------------------------------------;dl中保存下行楼层的最大值,还需要考虑没有下行的情况
Down_max:inc bxmov cx,bxmov dl,00h;如果没有元素的话可以保存lea di,outside
Loop_find:mov al,[di]cmp al,09h;如果没有下行的情况直接就退出了jae compare_up_down;超出范围了mov dl,[di]inc diloop loop_find
Compare_up_down:cmp ah,dljb up_bigmov max,ahjmp max_dir
Up_big:mov max,dl
;-----------------------------------------------
;加入的重要的判断运行方向部分
;判断当前楼层是否大于最大值,下行
;判断当前楼层是否小于最小值,上行
;如果最大值等于当前楼层也是要下行的因为已经派出了只有一个目标楼层的情况
;其实只需要判断一种情况即下行的情况即可其余都为上行
Max_dir:mov al,maxmov ah,current_floordec ah;current_floor要改为从0开始cmp ah,aljae down_runningjmp up_running
down_running:;确定运行方向上行mov al,00hmov dir,al;改变dir,00h表示下行 jmp Down_sorted
up_running:;确定运行方向下行mov al,01hmov dir,al;改变dir,01h表示上行
;-----------------------------------------------
;要先对其进行拍好顺序
Up_sorted:;正方向的排序
;a.内部按键大于当前楼层和外部按键高于当前楼层上行
;b.所有外部按键的下行和内部按键低于当前楼层
;c.外部按键低于当前楼层的上行
;-----------------------------------------------
;a.内部按键大于当前楼层和外部按键高于当前楼层上行;排序Seq中的数据lea di,seq;di表示内部按键lea si,tmp;si表示临时存储空间mov cl,nummov ch,00hcmp cx,00hje up_out_amov al,current_floordec al
Loop_seq_up1:cmp al,[di]ja back_seq_up_loop1;大于的话不加入mov ah,[di]call add_to_tmp;小于等于皆可
Back_seq_up_loop1:inc diloop Loop_seq_up1;排序Outside中的数据,并且必须是上行方向,自动满足了
Up_out_a:lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_up_amov al,current_floordec al
Loop_out_up1:cmp al,[di];al=04hja back_out_up_loop1mov ah,09hcmp ah,[di]jbe back_out_up_loop1;09h小于等于[di]说明是下行0不加入mov ah,[di]call add_to_tmp;要小于09h且大于等于current_floor的值
Back_out_up_loop1:inc diloop Loop_out_up1;--------------------------------------;先对ordered中的数据进行排序lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数mov sort_dir,00h;选择正向排序call bubble;--------------------------------------;再删除排好序之后重复的元素lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数call delete_repeatmov tmp_num,dh;--------------------------------------
End_up_a:call move_tmp_order;需要进行排序排序以后去除重复的元素call clear_tmp
;--------------------------------------------------
;b.所有外部按键的下行和内部按键低于当前楼层lea di,seqlea si,tmpmov cl,nummov ch,00hcmp cx,00hje up_out_bmov al,current_floordec al
Loop_seq_up2:cmp al,[di]jbe back_seq_up_loop2;大于等于的话不加入mov ah,[di]call add_to_tmp;小于加入
Back_seq_up_loop2:inc diloop Loop_seq_up2;排序Outside中的数据,加入所有方向向下的元素
Up_out_b:lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_up_b
Loop_out_up2:mov al,[di]cmp al,09hjb back_out_up_loop2;小于09h的都是上行,不加入sub al,08h;上行因此要减去09hmov ah,alcall add_to_tmp;加入所有下行元素
Back_out_up_loop2:inc diloop Loop_out_up2	;--------------------------------------
End_up_b:;如果只有一个元素有的话只需要倒序,其实不需要去除重复lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数mov sort_dir,01h;选择正向排序call bubble;;--------------------------------------lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数call delete_repeatmov tmp_num,dh;--------------------------------------call move_tmp_ordercall clear_tmp
;--------------------------------------------------
;c.外部按键低于当前楼层的上行;外部按键低于当前楼层的上行lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_up_cmov al,current_floordec al
Loop_out_up3:cmp [di],aljae back_out_up_loop3mov ah,[di]call add_to_tmp;小于al且上行
Back_out_up_loop3:inc diloop Loop_out_up3call move_tmp_ordercall clear_tmp;--------------------------------------lea di,orderedmov cl,ordered_num;cx为比较轮数,大循环次数call delete_repeatmov ordered_num,dh
End_up_c:jmp end_pro
;--------------------------------------------------	
Down_sorted:;先向下运行的结果
;a.内部按键小于当前楼层和外部按键低于当前楼层下行
;b.所有外部按键的上行
;c.外部按键高于当前楼层的下行
;--------------------------------------------------	
;a步骤;排序Seq中的数据lea di,seq;di表示内部按键lea si,tmp;si表示临时存储空间mov cl,nummov ch,00hcmp cx,00hje down_out_amov al,current_floordec al
Loop_seq_down1:;不需要比较全部加入mov ah,[di]call add_to_tmpinc diloop Loop_seq_down1;排序Outside中的数据,并且必须是下行方向,且低于当前楼层
Down_out_a:	lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_down_amov al,current_floordec aladd al,08h;要加上08h才可以比较
Loop_out_down1:mov dl,[di]cmp dl,09hjb back_out_down_loop1;小于09h表示上行cmp al,[di];只加入小于等于当前楼层的楼层jb back_out_down_loop1mov ah,[di]sub ah,08hcall add_to_tmp;要小于09h且大于等于current_floor的值
Back_out_down_loop1:inc diloop Loop_out_down1
End_down_a:;--------------------------------------;先对ordered中的数据进行排序lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数mov sort_dir,01h;选择反向排序call bubble;--------------------------------------;再删除排好序之后重复的元素lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数call delete_repeatmov tmp_num,dh;--------------------------------------call move_tmp_order;需要进行排序排序以后去除重复的元素call clear_tmp
;--------------------------------------------------
;b步骤
;所有外部按键的上行lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_down_b
Loop_out_down2:mov al,[di]cmp al,09hjae back_out_down_loop2;小于09h的都是下行,不加入mov ah,alcall add_to_tmp;加入所有下行元素
Back_out_down_loop2:inc diloop Loop_out_down2	;--------------------------------------call move_tmp_ordercall clear_tmp
End_down_b:
;--------------------------------------------------	
;c步骤;外部按键高于当前楼层的下行lea di,Outsidemov cl,out_nummov ch,00hcmp cx,00hje end_down_cmov al,current_floordec aladd al,08h
Loop_out_down3:cmp [di],aljbe back_out_down_loop3;大于al且下行mov ah,[di]sub ah,08hcall add_to_tmp;小于al且上行
Back_out_down_loop3:inc diloop Loop_out_down3;--------------------------------------;先对tmp中的数据进行反序lea di,tmpmov cl,tmp_num;cx为比较轮数,大循环次数mov sort_dir,01h;选择反向排序call bubble;--------------------------------------call move_tmp_order;移动call clear_tmp;--------------------------------------lea di,ordered;ordered整体去重mov cl,ordered_num;cx为比较轮数,大循环次数call delete_repeatmov ordered_num,dh;--------------------------------------
End_down_c:jmp end_pro
end_pro:   
;------------------------------------------ 
;测试显示部分;mov row,01h;设置行;mov line,00h;设置列;mov bx,00h;mov al,ordered[bx];call show_number;mov cl,ordered_num;mov ch,00h;lea di,ordered
;Loop_ascii:;mov al,[di];add al,'0';mov [di],al;inc di;loop loop_ascii;;lea di,ordered;mov cl,ordered_num;call show_string;jmp $
;--------------------------------------------pop dxpop cxpop bxpop axret
Process endpAdd_to_tmp proc near;加入tmp中mov [si],ahinc siinc tmp_numret
Add_to_tmp endpClear_tmp proc near;清除mov tmp_num,00hlea si,tmpret
Clear_tmp endpMove_tmp_order proc near;将tmp中的数据转移到ordered中保存mov cl,tmp_nummov ch,00hcmp cx,00h;tmp中没有元素不需要转移je exitmov bl,ordered_nummov bh,00hlea si,tmp
Loop_move:mov al,[si]mov ordered[bx],alinc bxinc siinc ordered_numloop loop_move
exit:ret
Move_tmp_order endp
;-----------------------------------------------
Bubble proc near;冒泡排序cmp cx,01h;小于等于1说明不需要使用冒泡排序jbe end_bubblemov si,di;备份di中的数据;冒泡排序部分mov ch,00hdec cx
Loop_sort1:mov dx,cx;dx表示大循环次数;mov bx,0;地址指针;lea di,seqmov di,si
Loop_sort2:;mov al,seq[bx]mov al,[di];cmp al,seq[bx+1]cmp sort_dir,01hje ir_dircmp al,[di+1]jbe no_change
Loop_back:;xchg al,seq[bx+1]xchg al,[di+1];mov seq[bx],al;在这里相当于溢出多给num了值mov [di],al
no_change:;inc bxinc diloop loop_sort2mov cx,dx;一轮比完之后,cx再次赋值比较轮数loop loop_sort1jmp end_bubble
Ir_dir:cmp al,[di+1]jae no_changejmp Loop_back
End_bubble:ret
Bubble endp	Delete_repeat proc near;数据放在di中,数据长度放在cl中cmp cl,01h;排除只有无元素和一个元素的情况jbe end_deletemov dh,cl;备份一下数据,表示元素的个数dec cl;真实比较的次数要比实际元素的个数少一个
Loop_delete:mov al,[di]cmp al,[di+1]je delete
Back_loop:;将后面的元素都往前移动inc diloop loop_deletejmp exit
Delete:;如果相等的是最后一个元素的情况cmp cl,01hje End_repeat;说明重复的是倒数两个元素dec dhpush cxpush didec cx;mov cx,01h
Loop_delete2:mov dl,[di+2]mov [di+1],dlinc diloop loop_delete2pop dipop cxdec cxjmp back_loop
End_repeat:dec dh;不需要dec cx了因为已经不会再进行比较了ret
End_delete:mov dh,cl
Exit:ret
Delete_repeat endp
;-------------------------------------------------------
Disp proc near;数码管显示部分push cxpush bxmov cl,num;元素的个数放入cl中mov ch,00h;为后面的loop做准备mov bh,00h;为后面的bx做序号做准备lea di,seq;seq的取值为0到7lea si,led;输出的数据应该是led中的数据mov al,00h;为之后的与运算做好准备cmp cl,00hje stop2cmp cl,03hja lights_out
Loop1:mov bl,[di];求得当前的序号,下表or al,led[bx];由下标值求得对应的元素值inc diloop loop1mov dx,First_Aout dx,almov current_led,al;保存上一次输出的数据为熄灭做准备jmp stop2
lights_out:mov num,00hmov al,00h;这里不应该只对应显示功能在后面的停止电梯中页应该用到mov dx,First_Aout dx,al
stop2:pop bxpop cxret
Disp endpdelay proc near;软件延时程序push cxpush axmov cx,011h
D1:mov ax,00ffh
D2:dec axjnz d2loop d1pop axpop cxret
delay endp
;-------------------------------------------------
Lcd_main proc nearcall Lcd_init
restart:mov row,00h;设置行mov line,03h;设置列lea di,buf1;显示'Welcome'mov cl,length1call show_string	ret
Lcd_main endpSet_cursor proc nearpush bxmov bl,linemov bh,rowcmp bh,00hja row_2;大于说明再第二行
Row_1:add bl,00hor bl,80hmov al,bljmp stop	
Row_2:add bl,40hor bl,80hmov al,bl
Stop:pop bxret
Set_cursor endpShow_string_clear proc near;数据在di中,长度在cl中push axpush bxpush cxmov ch,00hmov cl,05hcall set_cursor;得到的al的结果即为要显示的数据的位置call Lcd_wcmd
;------------------------------------mov cl,05h
Loop_clear:mov al,' 'call Lcd_wdataloop Loop_clearpop cxpop bxpop axret
show_string_clear endpShow_string proc near;数据在di中,长度在cl中push axpush bxmov ch,00h;push cx;将cl压栈call set_cursor;得到的al的结果即为要显示的数据的位置call Lcd_wcmd
;------------------------------------;mov cl,05h
;Loop_clear:;mov al,' ';call Lcd_wdata;loop Loop_clear;pop cx;将cl出栈;call set_cursor;重新定位;call Lcd_wcmd
;------------------------------------
Loop1:mov al,[di]call Lcd_wdatainc diloop Loop1pop bxpop axret
show_string endpShow_number proc near;根据当前al中的数据判断显示什么数据push axmov ah,'0'add al,ah;mov row,00h;设置行;mov line,02h;设置列mov [di],almov cl,01hcall show_stringpop axret
show_number endpLcd_init proc near;初始化函数mov dx,Second_MODEmov al,88h;全为输出,C的高位设置成输入模式out dx,almov al,38h;16*2显示,5*7点阵,8位数据接口call Lcd_wcmd     mov al,0ch;显示器开,光标关闭call Lcd_wcmdmov al,06h;文字不动,地址自动+1call Lcd_wcmdmov al,01h;清屏call Lcd_wcmdret
Lcd_init endpLcd_wcmd proc near;写命令函数,把命令存储在al中call waitready	mov bl,00h;RS和RW都为低电平表示命令模式,输出call RW_RS_setmov bl,01h;先需要设置E为低电平call E_setmov dx,Second_Aout dx,almov bl,00h;再设E为高电平call E_setret
Lcd_wcmd endpLcd_wdata proc near;写数据函数,把数据存储在al中call waitreadymov bl,01h;RS=1,RW=0表示数据模式,输出call RW_RS_setmov bl,01h;先需要设置E为低电平call E_setmov dx,Second_Aout dx,almov bl,00h;再设E为高电平call E_setret
Lcd_wdata endpWaitready proc nearpush axmov dx,Second_A;先输出A口为0ffhmov al,0ffhout dx,almov bl,02h;RS=0,RW=1表示命令模式,输入call RW_RS_set
Loop1:mov bl,01hcall E_setmov dx,Second_C;从C口读入命令字in al,dxtest al,80h;与运算判断输入的第八位是否为1mov bl,00hcall E_setjnz loop1;高位为1表示还没有处理完pop axret
Waitready endpRW_RS_set proc near;对应PB0,PB1,先把数据存在bl中;00表示RW=RS=0,01表示RW=0,RS=1,02表示RW=1,RS=0push axmov dx,Second_Bmov al,blout dx,alpop axret
RW_RS_set endpE_set proc near;对应PC4,先把数据存在bl中push axmov dx,Second_Cmov al,blout dx,alpop axret
E_set endp
;-------------------------------------------------------
Timer proc near;产生2ms脉冲信号push axmov dx,MY8253_MODE     mov al,076h;01通道1,11先读写低字节后读写高字节,011方式3,0二进制计数out dx,almov dx,MY8253_COUNT1mov ah,0f4h;频率为1kHz,计数值为500,高位为01,低位为f4mov al,ahout dx,almov al,01hout dx,alpop axret
Timer endpPlay_music proc near;停止计数器的计数
FREQ:mov di,[si]cmp di,0je stopcall soundadd si,2add bx,2jmp freq
Stop:mov dx,Third_cmov al,00h;停止播放音乐out dx,alret
Play_music endpSound proc nearmov dx,MY8253_MODEmov al,0b6h;选择通道2,11先读写低字节后读写高字节,011方式3,0二进制计数out dx,almov dx,2mov ax,307div dimov dx,MY8253_COUNT2out dx,almov al,ahout dx,almov ax,[bx]
sloop:mov cx,0018hloop $dec axjnz sloopret
Sound endp
;-------------------------------------------------------
Running proc nearpush bxpush cxmov row,01hmov line,04h  	lea di,buf6;显示'Run'mov cl,length6call show_string_clearcall show_stringmov dx,Third_modemov al,10000010B;A口输出,B口输入,C口第四位输出out dx,al;设置当前8255的模式mov al,current_floor;al中存储当前楼层mov ah,aim_floor;ah中存储目标楼层cmp al,ah;-----------------------------------------;mov al,ah;call show_number;jmp $;-----------------------------------------ja down;当前楼层大于目标楼层下行jb up;当前楼层小于目标楼层上行je equal
Down:mov dl,00hmov current_dir,dlmov row,00hmov line,0bhlea di,buf3;显示'Down'mov cl,length3;call show_string_clearcall show_stringmov dx,Third_A;输出初始值即楼层到计数器out dx,almov dx,Third_Cmov al,03h;PC0=1因为要做减法计数器out dx,alcall Timer;开始运行
Down_loop:mov dx,Third_Bin al,dx;---------------------------------------------;mov ah,03h;mov stop_mode,ah;call stop_running;---------------------------------------------cmp al,ah;仍然大于目标楼层ja down_loopjmp stop
Up:mov dl,01hmov current_dir,dlmov row,00hmov line,0bhlea di,buf2;显示'Up'mov cl,length2	call show_stringmov dx,Third_A;输出初始值即楼层到计数器out dx,almov dx,Third_Cmov al,02h;PC0=0因为要做加法计数器out dx,alcall Timer
Up_loop:mov dx,Third_Bin al,dx	;---------------------------------------------;mov ah,02h;mov stop_mode,ah;call stop_running;---------------------------------------------cmp al,ah;仍然小于目标楼层jb up_loopjmp stop
Equal:mov dx,Third_Aout dx,al
Stop:mov dx,Third_Cmov al,04h;开始播放音乐的同时停止0.5s脉冲的输出out dx,almov Current_floor,ah;更新当前楼层mov al,ah;显示部分mov row,01hmov line,04hlea di,buf5;显示'Open'mov cl,length5call show_string;------------------------------------;播放乐曲部分mov si,offset tfreqmov bx,offset tdlycall Play_Musicmov row,00hmov line,0bhcall show_string_clear;清空up和down;-------------------------------------pop cxpop bxret
Running endp
;-------------------------------------------------------MOV AH,4CHINT 21HCODES ENDSEND START

更多推荐

Proteus电梯课设

本文发布于:2024-02-28 09:51:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1769615.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:电梯   Proteus

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!