Bienvenue dans l'univers 68hc11

Pages en cours de réalisation...; Version du 14 septembre 95



Utilisation de la maquette 68hc11 de l'étage Electronique
ANNEXES
Document rédigé par J. Weiss, septembre 95
Retour à la partie principale du document

4 Annexes

4.1 Annexe 1 : Boot ROM en $BF40 (mode bootstrap)
4.2 Annexe 2 : Boot ROM en $E000 (mode normal)
4.3 Annexe 3 : Talker PC Bug11 (talkJW.asc)
4.4 Annexe 4 : Programmes exemples
4.4.1 LCD_Time.asc : utilisation d'un 68hc811E2 en mode normal
4.4.2 LCD_A1.asc : utilisation d'un 68hc11A1 en mode bootstrap ou normal
4.5 Annexe 5 : Documentation sur l'afficheur LCD


4 Annexes

4.1 Annexe 1 : Boot ROM en $BF40 (mode bootstrap)

  Programme Boot ROM, placé en $BF40 (longueur : 192 octets)        

portd            equ 8          ; Port D
spcr             equ $28        ; SPI Control Register
baud             equ $2B
sccr2            equ $2D        ; SCI Control Register 2
scsr             equ $2E        ; SCI Status Register
scdr             equ $2F        ; SCI Data Register

        LDS #$FF                ; initialisation de la pile à $FF
        LDX #$1000              ; on place l'index à $1000 (base des registres)
        BSET spcr,X,#$20        ;
        LDAA #$A2               ;
        STAA baud,X             ;
        LDAA #$0C               ;
        STAA sccr2,X
        BSET sccr2,X,#$01
Att1    BRSET portd,X,#$01,Att1
        BCLR sccr2,X,#$01
Att2    BRCLR scsr,X,#$20,Att2
        LDAA scdr,X
        BNE  Cont1
        JMP  $B600
Cont1   CMPA #$55
        BEQ Cont3
        CMPA #$FF
        BEQ Cont2
        BSET baud,X,#$33
 Cont2  LDY #$0000
 Att3   BRCLR scsr,X,#$20, Att3
        LDAA scdr,X
        STAA $00,Y
        STAA scdr,X
        INY
        CPY #$0100
        BNE Att3
Cont3   JMP $0000

 
* contenu mémoire pour les vecteurs d'interruption
*
* $BFD6-$BFD7    $00C4    SCI
* $BFD8-$BFD9    $00C7    SPI

* $BFDA-$BFDB    $00CA    PAI  : Entrée compteur
* $BFDC-$BFDD    $00CD    PAOV : Débordement du compteur
* $BFDE-$BFDF    $00D0    TO   : Débordement du timer

* $BFE0-$BFE1    $00D3    OC5
* $BFE2-$BFE3    $00D6    OC4
* $BFE4-$BFE5    $00D9    OC3
* $BFE6-$BFE7    $00DC    OC2
* $BFE8-$BFE9    $00DF    OC1
* $BFEA-$BFEB    $00E2    IC3
* $BFEC-$BFED    $00E5    IC2
* $BFEE-$BFEF    $00E8    IC1
* $BFF0-$BFF1    $00EB    RTI
* $BFF2-$BFF3    $00EE    IRQ
* $BFF4-$BFF5    $00F1    XIRQ
* $BFF6-$BFF7    $00F4    SWI
* $BFFA-$BFFB    $00FA    COP
* $BFFE-$BFFF    $BF40    Reset

4.2 Annexe 2 : Boot ROM en $E000 (mode normal)

*            Programme Boot ROM, placé en $E000        

portd            equ 8          ; Port D
spcr             equ $28        ; SPI Control Register
baud             equ $2B
sccr2            equ $2D        ; SCI Control Register 2
scsr             equ $2E        ; SCI Status Register
scdr             equ $2F        ; SCI Data Register

        LDX  #$100A             ; chargement de l'index à $100A
Att2    BRCLR 0,X,#$01,Cont1    ; si port E(0) = 0, alors on continue en ROM
        jmp $B600               ; sinon on saute en EEPROM ($B600)
Cont1   LDAA #$93
        STAA option+Base_reg
        LDAA #$00
        STAA tmsk2+Base_reg
        LDAA #$00
        STAA $bprot+Base_reg
        LDS  #$65
        JSR  $E34B
        LDX  $047
        STX  $6F
        LDAA tctl1+Base_reg
        ORAA #$3
        STAA tctl1+Base_reg
        LDAA #$D0
        STAA $6E
        LDD  #$3F0D
        STD  $71
        JSR  $E1A8
        CLR  $A6
        INC  $A6
        CLR  $A8
        LDAA hprio+Base_reg
        ANDA #$20
        BEQ  $E07D
        LDAA #$3

...

 
* contenu mémoire pour les vecteurs d'interruption (mode normal)
* $FFD6-$FFD7    $00C4    SCI
* $FFD8-$FFD9    $00C7    SPI

* $FFDA-$FFDB    $00CA    PAI  : Entrée compteur
* $FFDC-$FFDD    $00CD    PAOV : Débordement du compteur
* $FFDE-$FFDF    $00D0    TO   : Débordement du timer

* $FFE0-$FFE1    $00D3    OC5
* $FFE2-$FFE3    $00D6    OC4
* $FFE4-$FFE5    $00D9    OC3
* $FFE6-$FFE7    $00DC    OC2
* $FFE8-$FFE9    $00DF    OC1
* $FFEA-$FFEB    $00E2    IC3
* $FFEC-$FFED    $00E5    IC2
* $FFEE-$FFEF    $00E8    IC1
* $FFF0-$FFF1    $00EB    RTI
* $FFF2-$FFF3    $00EE    IRQ
* $FFF4-$FFF5    $00F1    XIRQ
* $FFF6-$FFF7    $00F4    SWI
* $FFFA-$FFFB    $00FA    COP
* $FFFE-$FFFF    $E000    Reset

4.3 Annexe 3 : Talker PC Bug11 (talkJW.asc)

*************************** TALKjw.ASC juillet 95 ************************
*   MCU resident, Interrupt driven Communication routines for 68HC11     *
*   monitor. Provides low level memory and stack read/write operations.  *
*                                                                        *
* CONSTANTES
TALKBASE  equ $0000
BOOTVECT  equ $00C4       ; adresse du vecteur SCI
STACK     equ $00EB       ; Départ de la pile
REGBASE   equ $1000       ; base des registres
*
JSCI      equ $00C4       ; adresse du vecteur SCI
JXIRQ     equ $00F1       ; adresse du vecteur XIRQ (pas utilisé)
JSWI      equ $00F4       ; adresse du vecteur SWI
JILLOP    equ $00F7       ; adresse du vecteur illegal Op Code (pas utilisé)
JCOP      equ $00FA       ; adresse du vecteur illegal Op Code (pas utilisé)
JMPEXT    equ $7E         ; mnémonique de l'instruction JMP
BRKCODE   equ $4A         ; signal d'arrêt vers l'IBM-PC
BRKACK    equ $4A         ; reconnaissance du signal d'arrêt par l'IBM-PC
*
* REGISTRES
BAUD      equ $2B
SCCR1     equ $2C
SCCR2     equ $2D
SCSR      equ $2E
SCDR      equ $2F
*
RDRF      equ $20
TDRE      equ $80
OR        equ $08
FE        equ $02
*
* PROGRAM
          org TALKBASE
TLKRSTART EQU *           ; allocation de la table des sauts des vecteurs d'interruption
          LDAA #JMPEXT
          LDY #NULLSRV
          LDX #BOOTVECT
SETVECT   EQU *
          STAA ,X
          INX
          STY ,X
          INX
          INX
          CPX #$100
          BNE SETVECT
          LDX #SCISRV
          STX JSCI+1
          LDX #TLKRSTART
          STX JILLOP+1
*
USERSTART EQU *
          LDS #STACK
          LDX #REGBASE
          CLR SCCR1,X
          LDD #$302C
          STAA BAUD,X       ; initialise SCI à 9600 baud, sans parité ni interruption
          STAB SCCR2,X      ; validation de tx & rx.
          LDAA #$40         ; validation des interruptions STOP et I, inhibition de XIRQ
          TAP
*
IDLE      JMP IDLE          ; attente d'une interruption SCI (provenant de l'IBM-PC)
* une commande RESET de l'IBM-PC change cette adresse de saut vers l'adressse de 
* départ de programme utilisateur
*
SCISRV    EQU *             ; détection de l'interruptio
          LDAA SCSR+REGBASE ; on suppose qu'elle vient du SCI
          ANDA #RDRF
          BEQ SCISRV        ; sinon on boucle
*
RXSRV     EQU *             ; Traitement de la donnée reçue
          LDAA SCDR+REGBASE ; lecture de l'octet de commande & echo de celui-ci
          COMA              ; inversion des données
          BSR OUTSCI        ; réexpédition vers l'IBM-PC
          BPL INH1          ; Bit 7 à 1, alors on traite la commande
          BSR INSCI         ; sinon on lit l'octet de comptage dans ACCB.(0=256)
          XGDX              ; X <--> Accd : sauve la commande et l'octet de comptage dans X
          BSR INSCI         ; lecture de la partie haute de l'adresse
          TBA               ; AccA <-- AccB
          BSR INSCI         ; lecture de la partie haute de l'adresse
          XGDX              ; X <--> Accd : récupère la commande et l'octet de comptage dans X
          CMPA #$FE
          BNE RXSRV1        ; s'agit-il d'une lecture mémoire ?
*
TREADMEM  EQU *         ; Lecture mémoire
          LDAA ,X            ; lecture à l'adresse concernée
          BSR OUTSCI         ; envoi à l'IBM-PC
          TBA                ; AccA <-- AccB : sauve l'octet de comptage
          BSR INSCI          ; attente de l'echo
          TAB                ; AccB <-- AccA : récupère l'octet de comptage
          INX                ; incrémentation de l'adresse
          DECB               ; décrémentation de l'octet de comptage
          BNE TREADMEM       ; boucle tant qu'il y a des cases à lire
          RTI                ; attente d'une nouvelle interruption
*
RXSRV1    EQU *
          CMPA #$BE
          BNE RXSRVEX        ; s'agit-il d'une écriture mémoire ?
*
          TBA                ; AccA <-- AccB : sauve l'octet de comptage
TWRITMEM  EQU *        ; Écriture mémoire
          BSR INSCI          ; lecture de l'octet suivant dans AccB
          STAB ,X            ; lecture à l'adresse concernée
          LDAB ,X            ; vérification de l'écriture
          STAB SCDR+REGBASE  ; echo vers l'IBM-PC
          INX                ; incrémentation de l'adresse
          DECA               ; décrémentation de l'octet de comptage
          BNE TWRITMEM       ; boucle tant qu'il y a des cases à lire
RXSRVEX   EQU *         
NULLSRV   RTI                ; attente d'une nouvelle interruption
*
INSCI     EQU *        ; Lecture sur le port série (SCI)
          LDAB SCSR+REGBASE  ; attente de RDRF=1
          BITB #(FE+OR)      ; s'agit-il d'un break
          BNE TLKRSTART      ; si oui, on redémarre le talker
          ANDB #RDRF
          BEQ INSCI
          LDAB SCDR+REGBASE  ; Lecture de la donnée provenant de l'IBM-PC
          RTS                ; retour avec la donnée dans AccB
*
OUTSCI    EQU *          ; Lecture sur le port série (SCI); seul Y est modifié
          XGDY               ;  AccD <--> Y 
OUTSCI1   LDAA SCSR+REGBASE
          BPL OUTSCI1        ; MS bit <> TDRE flag
          XGDY               ; AccD <--> Y
          STAA SCDR+REGBASE  ; Important : on réactualise  CCR
          RTS
*
INH1      EQU *
          CMPA #$7E          ; s'agit-il d'une lecture des registres ?
          BNE INH2
*
INH1A     TSX                ; X <- SP     : on place SP dans X
          XGDX               ; AccD <--> X : puis dans AccD
          BSR OUTSCI         ; on envoie SP (MSB)
          TBA
          BSR OUTSCI         ; on envoie SP (LSB)
          TSX                 X <- SP  : Récupère X (=stack pointer)
          LDAB #9            ; envoi dans la pile de 9 Octets
          BRA TREADMEM       ; i.e. CCR,ACCB,ACCA,IXH,IXL,IYH,IYL,PCH,PCL
*
INH2      EQU *
          CMPA #$3E          ; s'agit-il d'une lecture des registres ?
          BNE SWISRV1
*
          BSR INSCI          ; réception de SP (MSB) à partir de l'IBM-PC
          TBA           
          BSR INSCI          ; réception de SP (LSB) à partir de l'IBM-PC
          XGDX               ; AccD <--> X 
          TXS                ;  SP <-- X  
          LDAA #9            ; réception dans la pile de 9 Octets
          BRA TWRITMEM
*
SWISRV    EQU *            ; traitement des interruptions logicielles : SWI
          LDAA #BRKCODE      ; on envoie un signal de break à l'IBM-PC
          BSR OUTSCI          
SWIIDLE   CLI
          BRA SWIIDLE        ; on attend la réponse de l'IBM-PC (Ibit=0,Xbit=1)
*
SWISRV1   EQU *
          CMPA #BRKACK        ; acquitement du break par l'IBM-PC ?
          BNE RXSRVEX
          TSX                 X <- SP 
          LDAB #9
          ABX                 X <-- AccB + X
          TXS                 SP <-- X
          LDD 7,X             ; on pointe sur le 7ème octet (PCH) de l'état des registres
          BSR OUTSCI          ; adresse de retour du point d'arrêt (MSB)
          TBA
          BSR OUTSCI          ; adresse de retour du point d'arrêt (LSB)

          LDD #SWIIDLE        ; on force une boucle "bidon" pour le retour du break
          STD 7,X             ; on pointe sur le 7ème octet (PCH) de l'état des registres
          BRA INH1A           ; renvoi de l'état des registres à l'IBM-PC
*
          END

4.4 Annexe 4 : Programmes exemples

4.4.1 LCD_Time.asc : utilisation d'un 68hc811E2 en mode normal
*                          LCD_Time
* programme en eeprom   pour 68HC811E2
* Affichage de l'heure sur matrice LCD
* début de programme : $f800
*
*           J. Weiss juillet 95
*
* Les données sont transférées par le port série synchrone (SPI) :
* les transferts sont organisés sous forme de 2 envois vers la
* carte Clavier-afficheur et d'une lecture.
* Le programme utilise les interruption temps réel (RTI) pour l'horloge.
*
ddrd             equ 9          ; Data Direction Reg Port D
portd            equ 8          ; Port D
spcr             equ $28        ; SPI Control Register
spsr             equ $29        ; SPI Status Register
spdr             equ $2A        ; SPI Data Register
tmsk2            equ $24        ; Timer Mask Register 2
tflg2            equ $25        ; Timer Flag Register 2

************************************************************
*               Constantes du programme                    *
************************************************************

base_reg         equ $1000

** mots de commande (premier mot envoyé sur SPI)
RIEN             equ $FC  ; aucun affichage
LCD_on           equ $FF  ; affichage LCD
LCD_config       equ $FD  ; configuration de l'afficheur LCD
LED_on           equ $F6  ; sélection des LED
unites           equ $DE  ; sélection de l'afficheur des unités
dizaines         equ $EE  ; sélection de l'afficheur des dizaines
buzzer           equ $BE  ; sélection du buzzer 
relais           equ $7E  ; sélection du relais
switches         equ $10  ; interrupteurs

** mots de donnée (deuxième mot envoyé sur SPI)
LED_k1           equ $1   ; cathode de la LED 1 
LED_k2           equ $8   ; cathode de la LED 2 
LED_k3           equ $40  ; cathode de la LED 3 

************************************************************
*                variables du programme                    *
************************************************************
                 ORG $0000 ; on place les variables en bas de la RAM interne
c244             RMB 1    ; compte 244 interuptions RTI avant d'obtenir 1s.
bis              RMB 1    ; indique à ff que l'on a ajouté le reste
seconde          RMB 1    ; nbre de secondes de 0 à 256 pour ajustement
secondes         RMB 1    ; secondes de 0 à  59
minutes          RMB 1    ; minutes de 0 à 59
heures           RMB 1    ; heures de 0 à 23
data_in          RMB 1    ; lecture sur SPI
Commande_LCD     RMB 1	    ; mot de commande du LCD (0: commande; 2 : affichage)
digit1           RMB 1    ; digit des unités de l'afficheur LED
digit10          RMB 1    ; digit des dizaines de l'afficheur LED
touche           RMB 1    ; touche frappée sur le clavier (4 bits ou $FF si rien)
inter            RMB 1    ; interrupteurs (0 : S1, 1 : S2 et $FF : rien)
message          RMB 10   ; message à afficher

************************************************************
*             initialisation des vecteurs                  *
************************************************************
                 ORG  $FFFE
                 FDB  Rti            ; it périodique
                 ORG  $FFFE
                 FDB  Debut          ; début du programme
                 ORG  $F800

************************************************************
*                  Début du programme                      *
************************************************************
Debut            SEI                 ; set interrupt mask
                 LDX  #base_reg      ; X <--- $1000
                 LDS  #$FF           ; initialisation de la pile à FF

Depart           BSET pactl,x,#0       ; rti rate : 4,10 ms
                 BSET tmsk2,x,#$40     ; rti Interrupt Enable                   
                 CLR  secondes
                 CLR  minutes
                 CLR  heures
                 CLR  c244

************************************************************
*                 initialisation SPI                       *
************************************************************
Init_SPI         BSET ddrd,x,#$38    ; SS, SCK, MOSI en sortie
                 LDAA #$51           ; Enable SPI avec SCK=125kHz, wired_or mode
                 STAA spcr,x 
                 LDAA #$3F           ; on met les bits du port D à 1
                 STAA portd,x
                     
************************************************************
*                 initialisation LCD                       *
************************************************************
*Commande_LCD    RMB 1	  ; mot de commande du LCD (0: commande; 2 : affichage)
*LCD_config      equ $FD  ; configuration de l'afficheur LCD

Init_LCD         LDAA #LCD_config     ; mode config LCD
                 STAA Commande_LCD
                 LDAA #$1             ; clear Display
                 JSR  Aff_LCD

** l'afficheur a besoin d'une tempo
Tempo            LDY  #$1000          ; IY <- durée
T1               DEY                  ; IY <- IY-1
                 BNE  T1

                 LDAA #$E             ; display =on 
                 JSR  Aff_LCD
                 LDAA #$3C            ; N =2 lignes; F =  1 
                 JSR  Aff_LCD

***************************************************************
*   Départ du programme  *
***************************************************************
                 LDY  #introduction
                 JSR  Aff_msg
                 JSR  Affhm
B1               SEI
                 TST  c244
                 BNE  Go              ; on n'affiche que toutes les secondes
                 JSR  Affhm

Go               JSR Lect_clavier
                 JSR Aff_7seg
                 CLI                  ; Clear interrupt Mask                 
                 WAI	                ; Attente d'une interruption
                 JMP  B1

introduction     FCC ' Bonjour, il est   \'

*******************************************************************
*******************************************************************
* SP * envoi d'une chaine de caractères pointée par y finie par \ *
*******************************************************************
Aff_msg          LDAA #LCD_config       ; mode config LCD 
                 STAA Commande_LCD
                 LDAA #$80              ; DD Ram =$00
                 JSR  Aff_LCD
                 LDAA #LCD_on           ; mode Affichage LCD
                 STAA Commande_LCD		 
Envmot           LDAA 0,y
                 CMPA #'\'
                 BEQ  Envmot_fin        ; si \ alors retour
                 JSR  Aff_LCD           ; si non envoi du caractère (0,y)
                 INY                    ; IY <- IY + 1
                 BRA  Envmot            ; on boucle
Envmot_fin       RTS

******************************************************************
* SP *           préparation de l'affichage LCD                  *
******************************************************************
*Commande_LCD    RMB 1	  ; mot de commande du LCD (0: commande; 2 : affichage)
Aff_LCD          PSHB
                 LDAB Commande_LCD
                 JSR  OUTSPI	        ; on envoie la commande (E=1)
                 ANDB #$FE	        ; Disable	
                 JSR  OUTSPI	        ; on renvoie la commande (E=0)
                 PULB
                 RTS

*****************************************************************
* SP *  Envoi de 2 octets par SPI et réception d'un octet       *
*       - Le mot de commande est dans l'accumulateur B          *
*       - Les données en émission  sont dans l'accumulateur A   * 
*       - la donnée en réception est dans data_in               *
*****************************************************************
*data_in        RMB 1    ; lecture sur SPI

OUTSPI          PSHA              ; on empile la donnée
                PSHB              ; on empile le mot de commande
                PSHY                
                BCLR portd,x,#$20 ; met SS à 0 latche entrée et sortie registres
                STAB spdr,x       ; envoi du mot de commande

                LDY #08 	  ; 8 bits à faire tourner
RBBMIR          ROLA    	  ; les bits sortent à gauche par la retenue
                RORB		  ; et rentrent à droite par la carry
                DEY
                BNE RBBMIR
ATE20           BRCLR spsr,x,#$80 ATE20  ; attend fin transmission prec.
                LDAA  spdr,x             ; on récupère la donnée sur le SPI
                STAA  data_in            ; enregistre            
                STAB  spdr,x             ; on envoie la donnée sur le SPI
ATEF2O          BRCLR spsr,x,#$80 ATEF2O ; attend fin transmission pour reset SS        
                BSET  portd,x,#$20       ; met SS à 1 (delatche sorties registres)
                PULY
                PULB                     ; on restaure le mot de commande dans B
                PULA                     ; on restaure la donnée dans A
                RTS

*************************************************************************
* SP *        Affichage de l'heure sur l'afficheur LCD                  *
*************************************************************************
*seconde          RMB 1    ; nbre de secondes de 0 à 256 pour ajustement
*secondes         RMB 1    ; secondes de 0 à  59
*minutes          RMB 1    ; minutes de 0 à 59
*heures           RMB 1    ; heures de 0 à 23

Affhm           LDAA  #LCD_config  	    ; mode config LCD 
                STAA  Commande_LCD
                LDAA  #$C7               ; DD Ram =$47
                JSR   Aff_LCD
                LDAA  #LCD_on            ; RS  = 1 
                STAA  Commande_LCD
                LDAA  heures   
                JSR   Aff_ascii
                LDAA  #':'
                JSR   Aff_LCD
                LDAA  minutes   
                JSR   Aff_ascii
                LDAA  #':'
                JSR   Aff_LCD
                LDAA  secondes   
                JSR   Aff_ascii
                RTS

** envoi en DECIMAL ASCII du nombre contenu dans A
           
Aff_ascii       PSHB                   ; sauvegarde de B  
                JSR  Div_10            ; division par 10 de A
                STAA digit10
                STAB digit1
                ADDA #$30              ; A <- A + $30
                JSR  Aff_LCD           ; envoi du digit Quotient (dizaines)
                TBA	                 ; A <- B
                ADDA #$30              ; B <- B + $30
                JSR  Aff_LCD           ; envoi du digit Reste (unités)
                PULB pulb              ; restauration de B
                RTS   

** DIVISION PAR 10  ----------------------------
** donnee dans A -> A/10 ds A et reste ds B

Div_10          TAB                 ; B <-- A
                CLRA                ; A <- 0  : variable dans AccD
                LDX  #10            ; ix <- 10
                IDIV                ; Q:IX ; R:AccD <- AccD/IX
                PSHB                ; push B : Pile <- MSB du reste
                XGDX                ; Accd <-> IX
                TBA                 ; A <-- B
                PULB                ; pull B : B <- MSB du reste
                LDX  #base_reg      ; réinitialisation de IX ($1000)
                RTS                 ; return

*************************************************************************
* SP *        Affichage sur les afficheurs 7 segments LED               *
*                   digit1 correspond aux unités                        *
*                  digit10 correspond aux dizaines                      *
*************************************************************************
*digit1           RMB 1    ; digit des unités de l'afficheur LED
*digit10          RMB 1    ; digit des dizaines de l'afficheur LED

Aff_7seg        PSHY
                PSHB
                PSHA
                LDY  #Tab_7seg    ; on pointe sur la table de conversion
                LDAA c244         ; chargement du compteur d'horloge c244
                ASRA              ; on propage le LSB dans C
                BCC  Aff2         ; c244 est pair (C=0), on affiche les unités
                LDAB #dizaines    ; adresse du digit à afficher
                PSHB
                LDAB digit10      ; chargement du digit à afficher
                BRA  Fin_7seg

Aff2            LDAB #unites      ; adresse du digit à afficher
                PSHB
                LDAB digit1       ; chargement du digit à afficher
		
Fin_7seg        ABY               ;  Y <-- Y + B ( B :offset dans la table) 
                LDAA 0,y          ; pointage sur la table
                PULB              ; on récupère l'adresse du digit
                JSR  OUTSPI       ; envoi du digit 
                PULA
                PULB
                PULY
                RTS

*     segment :       dec.bafg                       
Tab_7seg        FCB #%11101110          ; chiffre 0
                FCB #%00101000          ; chiffre 1
                FCB #%11001101          ; chiffre 2
                FCB #%10101101          ; chiffre 3
                FCB #%00101011          ; chiffre 4
                FCB #%10100111          ; chiffre 5
                FCB #%11100111          ; chiffre 6
                FCB #%00101100          ; chiffre 7
                FCB #%11101111          ; chiffre 8
                FCB #%10101111          ; chiffre 9

******************************************************************************
* SP *             Lecture du clavier et des interrupteurs                   *
*            touche : lecture du clavier (4 bits ou $FF si rien)             *
*        inter : état des interrupteurs (0 : S1, 1 : S2 et $FF : rien)       *
******************************************************************************
*touche           RMB 1    ; touche frappée sur le clavier (4 bits ou $FF si rien)
*inter            RMB 1    ; interrupteurs (0 : S1, 1 : S2 et $FF : rien)

Lect_clavier    PSHA
                PSHB
                PSHY
Init_lect       LDAA #$FF
                STAA inter                
                STAA touche		
                LDAA #1                   ; on pointe sur la 1ère rangée
                LDAB #RIEN                ; mot de commande nul
                BRA Lect_2	          
Lect_1          ASLA                      ; rangée suivante
                BEQ Fin_lect              ; fin du balayage des rangées
Lect_2          JSR OUTSPI                ; on stimule
                JSR OUTSPI                ; on réceptionne la donnée (4 bits LSB)
                BRSET data_in,#$0F,Lect_1 ; réponse vierge ?, si oui on boucle
                COM data_in               ; complémentation de la donnée
                CMPA #switches            ; adressage des interrupteurs ?
                BEQ Lect_int              ; il 'agit d'un interrupteur !
                JSR Lin_bin               ; conversion en binaire (résultat dans B)
                PSHB                      ; sauvegarde du résultat "rangée"
                LDAA data_in              ; réponse "colonne"
                JSR Lin_bin               ; conversion en binaire (résultat dans B)
                ASLB
                ASLB
                PULA                      ; récupération du résultat "rangée"
                ABA                       ; mise en forme de la réponse clavier
                TAB
                LDY #Tab_clavier
                ABY
                LDAA 0,Y
                STAA touche		
Fin_lect        PULY
                PULB
                PULA 
                RTS

Lect_int        LDAA data_in
                RORA
                STAA inter
                BRA Fin_lect

Lin_bin         LDAB #0            ; compteur à zéro
Lin_1           RORA               ; on décale
                BCS Fin_lin        ; fin si on a propagé un 1 dans C
                CMPB #3            ; fin des 4 bits ?
                BEQ Fin_lin        ; si oui alors fin
                INCB               ; incrémentation du compteur
                BRA Lin_1          ; on boucle
Fin_lin         RTS

* on lit : 147A2580369BFEDC
Tab_clavier     FCB #$1
                FCB #$4
                FCB #$7
                FCB #$A
                FCB #$2
                FCB #$5
                FCB #$8
                FCB #$0
                FCB #$3
                FCB #$6
                FCB #$9
                FCB #$B
                FCB #$F
                FCB #$E
                FCB #$D
                FCB #$C
                           
******************************************************************
* INT *          Gestion de l'interruption périodique            *
* RTI *                  calcul de l'heure                       *
******************************************************************
*c244             RMB 1    ; compte 244 interuptions RTI avant d'obtenir 1s.
*bis              RMB 1    ; indique à ff que l'on a ajouté le reste
*seconde          RMB 1    ; nbre de secondes de 0 à 256 pour ajustement
*secondes         RMB 1    ; secondes de 0 à  59
*minutes          RMB 1    ; minutes de 0 à 59
*heures           RMB 1    ; heures de 0 à 23

** toutes les 256 s, on charge c244 avec le reste (16) pour ajuster l'horloge

Rti              DEC c244
                 BEQ Rti_0
                 JMP Fin_rti
Rti_0            BSET  c244,#244        ; recharge le compteur
                 BRSET bis,#$ff,Rti_1   ; bis indique que l'on a déjà re-
                                        * chargé c244 avec le reste
                 INC  seconde           ; inc sauf si bis = $ff
                                        * chaque fois que seconde passe à 0
                 BNE  Rti_2             ; on charge bis à ff et c244 à 16 (reste)
                                        * on ne compte pas cette "seconde"
Rti_01           LDAA #16               ; on charge le reste
                 STAA c244
                 BSET bis,#$ff
                 JMP  Fin_rti

Rti_1            CLR  bis
Rti_2            JSR  Affhm
                 LDAA #60
                 INC  secondes           ; secondes de 0 à 59
                 CMPA secondes
                 BNE  Fin_rti
                 CLR  secondes
                 INC  minutes
                 LDAA #60
                 CMPA minutes
                 BNE  Fin_rti            ; minutes
                 CLR  minutes
                 INC  heures
                 LDAA heures
                 CMPA #24
                 BNE  Fin_rti            ; heures
                 CLR  heures

Fin_rti          BCLR tflg2,x,#$BF      ; annule flag RTI
                 RTI

                END 

4.4.2 LCD_A1.asc : utilisation d'un 68hc11A1 en mode bootstrap ou normal
*                          LCD_A1
* programme en eeprom   pour 68HC11A1
* Affichage de l'heure sur matrice LCD
* début de programme : $B600
*           J. Weiss juillet 95
*
* Les données sont transférées par le port série synchrone (SPI) :
* les transferts sont organisés sous forme de 2 envois vers la
* carte Clavier-afficheur et d'une lecture.
* Le programme utilise les interruption temps réel (RTI) pour l'horloge.
*

ddrd             equ 9          ; Data Direction Reg Port D
portd            equ 8          ; Port D
spcr             equ $28        ; SPI Control Register
spsr             equ $29        ; SPI Status Register
spdr             equ $2A        ; SPI Data Register
tmsk2            equ $24        ; Timer Mask Register 2
tflg2            equ $25        ; Timer Flag Register 2

************************************************************
*               Constantes du programme                    *
************************************************************

base_reg         equ $1000
JUMPEXT          equ $7E             ; mnémonique de l'instruction JMP
JRTI             equ $00EB           ; adresse du vecteur RTI

** mots de commande (premier mot envoyé sur SPI)
RIEN             equ $FC  ; aucun affichage
LCD_on           equ $FF  ; affichage LCD
LCD_config       equ $FD  ; configuration de l'afficheur LCD
LED_on           equ $F6  ; sélection des LED
unites           equ $DE  ; sélection de l'afficheur des unités
dizaines         equ $EE  ; sélection de l'afficheur des dizaines
buzzer           equ $BE  ; sélection du buzzer 
relais           equ $7E  ; sélection du relais
switches         equ $10  ; interrupteurs

** mots de donnée (deuxième mot envoyé sur SPI)
LED_k1           equ $1   ; cathode de la LED 1 
LED_k2           equ $8   ; cathode de la LED 2 
LED_k3           equ $40  ; cathode de la LED 3 

************************************************************
*                variables du programme                    *
************************************************************
                 ORG $00B0 ; on place les variables en $B0
c244             RMB 1    ; compte 244 interuptions RTI avant d'obtenir 1s.
bis              RMB 1    ; indique à ff que l'on a ajouté le reste
seconde          RMB 1    ; nbre de secondes de 0 à 256 pour ajustement
secondes         RMB 1    ; secondes de 0 à  59
minutes          RMB 1    ; minutes de 0 à 59
heures           RMB 1    ; heures de 0 à 23
data_in          RMB 1    ; lecture sur SPI
Commande_LCD     RMB 1	    ; mot de commande du LCD (0: commande; 2 : affichage)
digit1           RMB 1    ; digit des unités de l'afficheur LED
digit10          RMB 1    ; digit des dizaines de l'afficheur LED
touche           RMB 1    ; touche frappée sur le clavier (4 bits ou $FF si rien)
inter            RMB 1    ; interrupteurs (0 : S1, 1 : S2 et $FF : rien)
message          RMB 10   ; message à afficher

************************************************************
*             initialisation des vecteurs                  *
************************************************************
                 ORG  $B600          ; adresse de l'EEPROM
Debut            SEI                 ; set interrupt mask
                 LDAA #JUMPEXT       ; mnémonique de l'instruction JMP
                 LDX  #Rti           ; adresse du sous-programme d'IT (ici : RTI)
                 STAA JRTI           ; ecriture de JMP Rti à partir de l'adresse $EB
                 STX  JRTI+1         ;
                 LDX  #base_reg      ; X <--- $1000
                 LDS  #$EA           ; initialisation de la pile à $EA

Depart           BSET pactl,x,#0       ; rti rate : 4,10 ms
                 BSET tmsk2,x,#$40     ; rti Interrupt Enable                   
...

La suite du programme est identique au programme précédent (LCD_time.asc) à partir de l'étiquette Depart.

4.5 Annexe 5 : Documentation sur l'afficheur LCD

Retour à la partie principale du document


Remarques à Jacques.Weiss@supelec.fr