Communication série rs232 avec interruptions

Description

Ce code permet la communication série entre deux PCs. Lors de la reception d'un nouveau caractère sur la liaison série, l'interruption IRQ4 se déclenche, et une routine prend en charge son traitement. Une interruption est aussi générée dans le cas d'une erreur de réception.

Source / Exemple :


.386

donnees segment

;;;;;;;;;;;;;;; Port COM ;;;;;;;;;;;;;;;;;;;;

commprt equ     03F8h           ; adresse de base du com1
THR     equ     commprt         ; THR
DL_LSB  equ     commprt         ; divisor latch LSB
DL_MSB  equ     commprt+1       ; divisor latch MSB
IER     equ     commprt+1       ; IT enable
IIR     equ     commprt+2       ; IT identification
FCR     equ     commprt+2       ; Fifo ctrl register
LCR     equ     commprt+3       ; ctrl ligne
MCR     equ     commprt+4       ; ctrl modem
LSR     equ     commprt+5       ; status ligne
MSR     equ     commprt+6       ; status modem

;;;;;;;;;;;;;;; Controlleur d'interruption ;;;;;;;;;

interr  equ     21h

donnees ends

pile    segment stack
        dw      80      dup(?)
pile    ends

code	segment use16

assume cs:code,ds:donnees
prog    proc    far

        ;;;;;;;;;;;;; Sauvegarde des registres ;;;;;;;;;;;;;;;

        push    ds
        push    es
        push    ax
        push    si
        push    dx

        ;;;;;;;;;;;;; Initialisation des registres de segments ;;;;;;;;;;;;;;;;;;

        mov     ax,donnees
        mov     ds,ax
        mov     es,ax

        ;;;;;;;;;;;;; détournement de l'IRQ4 ;;;;;;;;;;;;;;;;;

        cli                     ; désactive les interruptions
	xor	ax,ax
        mov     fs,ax           ; fs = 0
        mov     dx,interr
        in      al,interr       ; lecture du masque d'interruption
        and     al,0EFh         ; démasque l'IRQ4
        out     dx,al           ; écriture du masque
        mov     ax,cs           ;
	shl	eax,16		; eax = cs00h
        mov     ax,offset irq4  ; eax contient segment et offset de la nvlle routine d'interruption
        mov     fs:[0Ch*4],eax  ; détourne l'irq4

        ;;;;;;;;;;;;; Initialisation du port COM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        mov     al,80h          ; DLAB=1
        mov     dx,LCR
        out     dx,al
	
        mov     al,0Ch          ; 9600 bits/s
        mov     dx,DL_LSB
        out     dx,al
	xor	al,al
        mov     dx,DL_MSB
        out     dx,al
	
        mov     al,03h          ; DLAB=0, 8 bits de données, 1 bit d'arrêt, aucune parité
        mov     dx,LCR
        out     dx,al
	
        mov     al,5           	; Active l'interruption donnee prete et l'interruption de changement du status de ligne
        mov     dx,IER
        out     dx,al

        sti                     ; Autorise les interruptions

        ;;;;;;;;;;;;; programme principal ;;;;;;;;;;;;;;;;;;;;;;
        

start:
        xor     si,si
        lea     dx,moi
        mov     ah,09h
        int     21h

loop1:
        xor     ax,ax           ; lecture d'un caractère
	int	16h
        call    send_char

        cmp     al,27           ; teste si touche=esc
        jz      fin	        ; sortir

        mov     dl,al           ; afficher le caractère
        mov     ah,02h
        int     21h

        jnz     loop1

send_quit:
        call    send_char
fin:
        pop     dx
        pop     si
        pop     ax
        pop     es
        pop     ds

        mov	ax,4C00h
	int	21h
prog    endp

irq4:                           
	push	ax
	push	dx
        push    ds
        
        ;;;;; Source de l'interruption ;;;;;;

        mov     dx,IIR
        in      al,dx
        and     al,6            ; conserver que bits 1 et 2
        test    al,6
        jz      erreur_ligne    ; erreur ligne

                                ; sinon donnée prête
        mov     dx,commprt      ; lit un caractère du tampon de réception
        in      al,dx

        mov     dl,al
        mov     ah,02h          ; l'affiche à l'écran
        int     21h
        jmp     fin_irq4

erreur_ligne:
        mov     dx,LSR          ; lecture de l'état de la ligne
        in      al,dx
        test    al,2            ; si bit 1 est = 1 => erreur overrun
        jz      overrun
        test    al,8
        jz      cadrage         ; si bit 3 est = 1 => erreur cadrage (forme)
        jmp     fin_irq4

overrun:
        lea     dx,overrun_msg
        mov     ax,cs
        mov     ds,ax
        mov     ah,9
        int     21h
        jmp     fin_irq4

cadrage:
        lea     dx,cadrage_msg
        mov     ax,cs
        mov     ds,ax
        mov     ah,9
        int     21h

fin_irq4:
        mov     al,20h          ; EOI
	out	20h,al
        pop     ds
	pop	dx
	pop	ax
	iret

overrun_msg     db "erreur overrun$"
cadrage_msg     db "erreur cadrage$"

;;;;;;;;;;;;; routine d'envoi d'un caracactère ;;;;;;;;;;;;;;;;

send_char proc near
        push    dx
        push    ax
        mov     dx,LSR
attend:
        in      al,dx
        test    al,20h
        jz      attend
        pop     ax
        mov     dx,commprt
        out     dx,al
        pop     dx
        ret
send_char endp
           

code	ends
        end     prog

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.