主题:求高手帮我设计一个报警器
feitian739
[专家分:0] 发布于 2006-01-12 16:48:00
求高手帮我设计一个报警器
在屏幕上显示一个闪烁的红色报警指示灯(形状不限),是否报警可由用户控制,并有报警声音
qqq
回复列表 (共11个回复)
沙发
hm1024 [专家分:220] 发布于 2006-01-13 13:13:00
;我写了一个看适合你不,按Esc退出,按住空格键就会不停的发出蜂鸣声。
;用Masm5.0编译,不足的地方是程序在处理不同的显卡时对闪烁处理的不是很好。
data segment
assume ds:data
l_u dw 300,160
r_d dw 320,180
color db 4
speed dw 1000h
ending db 00h
EscFlag db 00h
data ends
code segment
assume cs:code
main proc far
mov ax,data
mov ds,ax
cli ;关中断,IF=0
mov al,09h
mov ah,35h
int 21h ;取系统09H类型中断向量
push es ;用堆栈保存
push bx
push ds ;设置09H 类型中断向量
mov dx,offset NewInt9
mov ax,seg NewInt9
mov ds,ax
mov al,09h
mov ah,25h
int 21h
pop ds
in al,21h ;设置8259A中断屏蔽字
and al,11111101b ;允许IR1键盘中断
out 21h,al
sti ;开中断, IF= 1
mov bh,07h
mov ax,0600h
xor cx,cx
mov dx,184fh
int 10h
mov ax,0012h
int 10h
draw: mov si,word ptr r_d
sub si,word ptr l_u
mov cx,word ptr l_u
b_loop1:mov di,word ptr r_d+2
sub di,word ptr l_u+2
mov dx,word ptr l_u+2
mov al,color
b_loop2:mov ah,0ch
int 10h
inc dx
dec di
jnz b_loop2
inc cx
dec si
jnz b_loop1
cmp color,4
je setcolor
mov color,4
jmp redraw
setcolor:mov color,0
redraw: call delay
test ending,80h ;如果用户按下Esc键那么程序结束
jz draw
pop dx ;恢复系统09H类型中断向量
pop ds
mov al,09h
mov ah,25h
int 21h
exit: mov ax,0003h
int 10h
mov ah,4ch
int 21h
main endp
delay proc near
mov cx,speed
d_time1:push cx
mov cx,speed
d_time2:loop d_time2
pop cx
loop d_time1
ret
delay endp
NewInt9 proc far ;重写INT 09H键盘中断服务程序
push ax ;保存现场
push bx
push cx
push dx
push si
push di
push bp
push ds
cli
xor cx,cx
NI_nody:in al,64
test al,02
loopnz NI_nody
in al,60h ;读入字符扫描码
cmp al,81h
jnz NI_mkbk ;松开的不是Esc键
or ending,80h
jmp NI_exit
NI_mkbk:and al,7fh
cmp al,39h
jne NI_exit
in al,61h
and al,11111100b
xor al,2
out 61h,al
mov cx,10
NI_beep:loop NI_beep
and al,11111100b
out 61h,al
NI_exit:mov al,20h ;发中断结束命令EOI
out 20h,al
sti
pop ds
pop bp
pop di
pop si
pop dx ;恢复现场
pop cx
pop bx
pop ax
iret ;中断返回
NewInt9 endp
code ends
end main
板凳
feitian739 [专家分:0] 发布于 2006-01-13 14:49:00
真是太感谢了 呵呵[em28][em28]
3 楼
feitian739 [专家分:0] 发布于 2006-01-13 14:59:00
不过好像显示不了那个报警指示灯啊
4 楼
hm1024 [专家分:220] 发布于 2006-01-13 15:24:00
你说的问题我解决掉了。在原来的基础上我改了三个地方,已经能够在屏幕的中间显示一个手指甲大小的红色方块,并且不断的闪烁。
我修改的三个地方是:
1、图形模式号原来是12H,现改为0EH,640*420,16色
2、坐标位置调整了一下,现改为:l_u dw 300,70 ;左上角坐标;r_d dw 320,80 ;右下角坐标
3、原来有一段程序是用来清屏的,主要通过滚屏实现清屏的,我估计原来的主要问题在于一是不同显卡的显示模式,二是滚屏把红色方块滚动过去了,你没看到,实际上已经有了。
============================================================================
改过的地方,我都做了记录。我相信应该没问了。
data segment
assume ds:data
l_u dw 300,70 ;左上角坐标 这里改过了!!!!!!!!!
r_d dw 320,80 ;右下角坐标
color db 4
speed dw 1000h
ending db 00h
EscFlag db 00h
data ends
code segment
assume cs:code
main proc far
mov ax,data
mov ds,ax
cli ;关中断,IF=0
mov al,09h
mov ah,35h
int 21h ;取系统09H类型中断向量
push es ;用堆栈保存
push bx
push ds ;设置09H 类型中断向量
mov dx,offset NewInt9
mov ax,seg NewInt9
mov ds,ax
mov al,09h
mov ah,25h
int 21h
pop ds
in al,21h ;设置8259A中断屏蔽字
and al,11111101b ;允许IR1键盘中断
out 21h,al
sti ;开中断, IF= 1
;这里改过了!!!!!!!!原来这还有一小段清屏的代码.
mov ax,000eh ;这里改过了!!!!原来的模式号为12h
int 10h
draw: mov si,word ptr r_d
sub si,word ptr l_u
mov cx,word ptr l_u
b_loop1:mov di,word ptr r_d+2
sub di,word ptr l_u+2
mov dx,word ptr l_u+2
mov al,color
b_loop2:mov ah,0ch
int 10h
inc dx
dec di
jnz b_loop2
inc cx
dec si
jnz b_loop1
cmp color,4
je setcolor
mov color,4
jmp redraw
setcolor:mov color,0
redraw: call delay
test ending,80h ;如果用户两次按下Esc键那么程序结束
jz draw
pop dx ;恢复系统09H类型中断向量
pop ds
mov al,09h
mov ah,25h
int 21h
exit: mov ax,0003h
int 10h
mov ah,4ch
int 21h
main endp
delay proc near
mov cx,speed
d_time1:push cx
mov cx,speed
d_time2:loop d_time2
pop cx
loop d_time1
ret
delay endp
NewInt9 proc far ;重写INT 09H键盘中断服务程序
push ax ;保存现场
push bx
push cx
push dx
push si
push di
push bp
push ds
cli
xor cx,cx
NI_nody:in al,64
test al,02
loopnz NI_nody
in al,60h ;读入字符扫描码
cmp al,81h
jnz NI_mkbk ;松开的不是Esc键
or ending,80h
jmp NI_exit
NI_mkbk:and al,7fh
cmp al,39h
jne NI_exit
in al,61h
and al,11111100b
xor al,2
out 61h,al
mov cx,10
NI_beep:loop NI_beep
and al,11111100b
out 61h,al
NI_exit:mov al,20h ;发中断结束命令EOI
out 20h,al
sti
pop ds
pop bp
pop di
pop si
pop dx ;恢复现场
pop cx
pop bx
pop ax
iret ;中断返回
NewInt9 endp
code ends
end main
5 楼
feitian739 [专家分:0] 发布于 2006-01-13 18:07:00
3Q了
不过能不能让那个红色方块和声音同步啊,也就是说按空格键之后才出现闪烁的红块,
而松开之后则消失
6 楼
hm1024 [专家分:220] 发布于 2006-01-14 08:20:00
;搞定了。
data segment
assume ds:data
l_u dw 300,70 ;左上角坐标
r_d dw 320,80 ;右下角坐标
color db 0 ;开始时显示为黑色的方块,按下空格键就黑红交替显示了
speed dw 1000
ending db 00h
EscFlag db 00h
data ends
code segment
assume cs:code
main proc far
mov ax,data
mov ds,ax
cli ;关中断,IF=0
mov al,09h
mov ah,35h
int 21h ;取系统09H类型中断向量
push es ;用堆栈保存
push bx
push ds ;设置09H 类型中断向量
mov dx,offset NewInt9
mov ax,seg NewInt9
mov ds,ax
mov al,09h
mov ah,25h
int 21h
pop ds
in al,21h ;设置8259A中断屏蔽字
and al,11111101b ;允许IR1键盘中断
out 21h,al
sti ;开中断, IF= 1
mov ax,000eh ;设置显示模式0Eh
int 10h
draw: mov si,word ptr r_d ;在屏幕中间画一个手指甲大小的方块
sub si,word ptr l_u
mov cx,word ptr l_u
b_loop1:mov di,word ptr r_d+2
sub di,word ptr l_u+2
mov dx,word ptr l_u+2
mov al,color
b_loop2:mov ah,0ch
int 10h
inc dx
dec di
jnz b_loop2
inc cx
dec si
jnz b_loop1
call delay ;延时
test ending,80h ;如果用户两次按下Esc键那么程序结束
jz draw
pop dx ;恢复系统09H类型中断向量
pop ds
mov al,09h
mov ah,25h
int 21h
exit: mov ax,0003h ;重置显示模式号
int 10h
mov ah,4ch
int 21h
main endp
delay proc near
mov cx,speed
d_time1:push cx
mov cx,speed
d_time2:loop d_time2
pop cx
loop d_time1
ret
delay endp
NewInt9 proc far ;重写INT 09H键盘中断服务程序
push ax ;保存现场
push bx
push cx
push dx
push si
push di
push bp
push ds
cli
xor cx,cx ;设置循环计数检测64h号I/O端口状态
NI_nody:in al,64h
test al,02
loopnz NI_nody
in al,60h ;读入字符扫描码
cmp al,81h
jnz NI_mkbk ;松开的不是Esc键
or ending,80h ;设置程序结束标志
jmp NI_exit
NI_mkbk:cmp al,0b9h ;空格键的按下时扫描码是39h,按住不松手是39h,松开时扫描码是0b9h
jne NI_space
mov color,0
jmp NI_exit
NI_space:cmp al,39h ;按住不松手时空格键的扫描码是39h
jne NI_exit
cmp color,4 ;原来时红色就变成黑色,原来是黑色就变成红色
je NI_color
mov color,4
jmp NI_sing
NI_color:mov color,0
NI_sing:in al,61h ;这里是用来发出声音的
and al,11111100b
xor al,2
out 61h,al
mov cx,10
NI_beep:loop NI_beep ;用来延时的
and al,11111100b
out 61h,al
NI_exit:mov al,20h ;发中断结束命令EOI
out 20h,al
sti
pop ds
pop bp
pop di
pop si
pop dx ;恢复现场
pop cx
pop bx
pop ax
iret ;中断返回
NewInt9 endp
code ends
end main
7 楼
hm1024 [专家分:220] 发布于 2006-01-14 11:29:00
给你这个看看,下面是关于键盘扫描码的介绍。
在Scan Code Set 1中,对于绝大多数键而言,其Make Code,Break Code,以及Repeat Code都是单字节的。其规则为:如果Make Code为nn,则其Repeat code与Make Code相同也是nn,而其Break Code则是将nn与80h进行按位OR运算,也就是将Make Code的最高位bit-7设置为1。比如:键"A"的Make Code位1Eh,其Repeat Code也为1Eh,而其Break Code则为1Eh|80h=9Eh。
还有一些键的Scan Code是双字节的。其规则为:它们的第一个字节都是E0h,对于第2个字节,其规则与单字节Scan Code的规则一样。
对PrtSc/SysRq键而言,其make code = E02AE037,repeat code = E037, break code = E0B7E0AA。
Pause/Break键没有Repeat Code,也没有Break Code,只有Make Code。其Make Code很长,为E11D45E19DC5。
8 楼
feitian739 [专家分:0] 发布于 2006-01-14 12:20:00
楼上的真是横人,哈哈哈
辛苦了,太感谢了 !!!
9 楼
hm1024 [专家分:220] 发布于 2006-01-14 12:23:00
不必客气,我也学到了不少东西。
10 楼
feitian739 [专家分:0] 发布于 2006-01-14 15:57:00
我还想问一下为什么那个红色方块在有的电脑上显示的挺好的,而在有的电脑上却显示不出来或者方块不闪烁,这个和显示器的分辨率有关吗?与程序里的图形模式号有什么关系吗?
我来回复