; Commande d'un afficheur LCD alphanumérique (interface 4 bits) ; Commande via RS232 ; Utilisation de l'USART du 16F628A avec interruptions ; 9600 bauds/s ; 8 bits de données ; Pas de bit de parité ; 1 bit de STOP ; Pas de contrôle de flux ; (C) Fabrice Sincère, juillet 2007 ; IUT Nancy-Brabois ; Version 1.02 ; Microcontrôleur PIC 16F628A ; Langage : assembleur ; Développé avec Microchip MPLAB IDE Errorlevel-302 ; Supprime le message "Ensure that bank bits are correct" List p=16F628A ; processeur utilisé #include __config _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF & _DATA_CP_OFF & _BOREN_ON & _MCLRE_ON ;bits de configuration : ;code protect OFF ;watchdog timer OFF ;power up timer ON (72 ms : cela permet d'initialiser l'afficheur LCD) ;oscillateur HS (quartz 20 MHz) ;low voltage program OFF ;data EE read protect OFF ;brown out detect ON ;master clear enable ON ;xxxxxx ; Macro ;xxxxxx bank1 macro ; passage en banque 1 bsf STATUS,RP0 bcf STATUS,RP1 endm bank0 macro ; passage en banque 0 bcf STATUS,RP0 bcf STATUS,RP1 endm ;xxxxxxxxxxxxxxxxxxxxxxxxxx ; Déclaration des variables ;xxxxxxxxxxxxxxxxxxxxxxxxxx CBLOCK 0x070 ; début de la zone des registres d'usage général du 16F628A ; (banque quelconque : 0,1,2 ou 3) ; 0x070 - 0x07F : 16 variables STATUS_TEMP : 1 ; sauvegarde du registre STATUS (routine d'interruption) W_TEMP : 1 ; sauvegarde du registre W (routine d'interruption) octet : 1 ; octet reçu (broche RX de l'UART) octet1 : 1 ; 1er octet reçu : contient le niveau des bits RS et R/W : ; (000000 RS R/W) octet2 : 1 ; 2eme octet reçu : contient le niveau des bits DB7-DB0 : ; (DB7 ... DB0) nb_octet_recu : 1 ; nombre d'octets reçus ; (valeur initiale : 0) octet_tx : 1 ; 8 bits à transmettre vers l'ordinateur (compteur d'adresse, ; ou 8 bits de données dans le cas de l'instruction "Read data from RAM") PORTA_comp : 1 ; niveaux du port A PORTB_comp : 1 ; niveaux du port B busy_flag : 1 ; seul le bit 0 est utilisé address_counter : 1 ; (0 DB6 ... DB0) datas : 1 ; 8 bits de données dans le cas de l'instruction "Read data from RAM" ENDC ;xxxxxxxxxxxxxxxxxxxx ; Démarrage sur reset ;xxxxxxxxxxxxxxxxxxxx org 0x0000 goto initialisation ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine d'interruption ; 2 sources d'interruption : ; - réception (UART) ; - émission (UART) ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxx org 0x0004 ; vecteur d'interruption movwf W_TEMP swapf STATUS,W movwf STATUS_TEMP ; sauvegarde du registre W puis du registre STATUS bank1 btfss PIE1, RCIE goto int1 bank0 btfsc PIR1, RCIF goto reception int1 bank1 btfss PIE1, TXIE goto int2 bank0 btfsc PIR1, TXIF goto emission int2 goto restauration ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Traitement de l'interruption de réception de l'USART ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx reception bank0 incf nb_octet_recu , f ; on incrémente (nb_octet_recu) movf RCREG , W ; N.B. le flag RCIF est remis à 0 par une lecture du registre RCREG movwf octet ; les 8 bits de données sont transférés dans (octet) movlw D'1' subwf nb_octet_recu , W btfss STATUS , Z goto rec2 ; réception du 1er octet movf octet , W movwf octet1 goto overrun rec2 ; réception du 2ème octet movf octet , W movwf octet2 clrf nb_octet_recu ; xxxxxxxxxxxxxxxxxxxxxxxxxxx ; test R/W btfss octet1 , 0 goto RW0 goto RW1 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; On traite ici les instructions d'écriture (R/W = 0) ; - Display clear ; - Return home ; - Entry mode set ; - Display On/Off Control ; - Cursor or display shift ; - Set function ; - Set CGRAM address ; - Set DDRAM address ; - Write Data to RAM RW0 ; 1ère étape : RS R/W , E = 0 ; E=0 (RB5) clrf PORTB_comp ; mise à jour RS (RB3) btfsc octet1 , 1 bsf PORTB_comp , 3 btfss octet1 , 1 bcf PORTB_comp , 3 ; mise à jour R/W (RB4) btfsc octet1 , 0 bsf PORTB_comp , 4 btfss octet1 , 0 bcf PORTB_comp , 4 movf PORTB_comp , W movwf PORTB ; mise à jour des sorties du port B ; 2ème étape : DB7 DB6 DB5 DB4 clrf PORTA_comp ; mise à jour DB7 (RA3) btfsc octet2 , 7 bsf PORTA_comp , 3 btfss octet2 , 7 bcf PORTA_comp , 3 ; mise à jour DB6 (RA2) btfsc octet2 , 6 bsf PORTA_comp , 2 btfss octet2 , 6 bcf PORTA_comp , 2 ; mise à jour DB5 (RA1) btfsc octet2 , 5 bsf PORTA_comp , 1 btfss octet2 , 5 bcf PORTA_comp , 1 ; mise à jour DB4 (RA0) btfsc octet2 , 4 bsf PORTA_comp , 0 btfss octet2 , 4 bcf PORTA_comp , 0 movf PORTA_comp , W movwf PORTA ; mise à jour des sorties du port A ; 3ème étape E=1 (RB5) bsf PORTB , 5 nop nop nop nop nop ; une pause de 1 µs (220 ns suffisent) ; 4ème étape E=0 (RB5) bcf PORTB , 5 ; 5ème étape DB3 DB2 DB1 DB0 clrf PORTA_comp ; mise à jour DB3 (RA3) btfsc octet2 , 3 bsf PORTA_comp , 3 btfss octet2 , 3 bcf PORTA_comp , 3 ; mise à jour DB2 (RA2) btfsc octet2 , 2 bsf PORTA_comp , 2 btfss octet2 , 2 bcf PORTA_comp , 2 ; mise à jour DB1 (RA1) btfsc octet2 , 1 bsf PORTA_comp , 1 btfss octet2 , 1 bcf PORTA_comp , 1 ; mise à jour DB0 (RA0) btfsc octet2 , 0 bsf PORTA_comp , 0 btfss octet2 , 0 bcf PORTA_comp , 0 movf PORTA_comp , W movwf PORTA ; mise à jour des sorties du port A ; 6ème étape E=1 (RB5) bsf PORTB , 5 nop nop nop nop nop ; une pause de 1 µs (220 ns suffisent) ; 7ème étape E=0 (RB5) bcf PORTB , 5 ; xxxxxxxxxxxxxxxxxxxxxxxx ; on teste le drapeau Busy fin_instruction call busy btfsc busy_flag , 0 goto fin_instruction ; drapeau Busy = 1 (instruction en cours) ; drapeau Busy = 0 : instruction terminée ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx movf address_counter , W movwf octet_tx bank1 bsf PIE1 , TXIE ; autorisation de l'interruption d'émission de l'USART bank0 goto overrun ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; On traite ici les instructions de lecture (R/W = 1) ; - Read Busy Flag & Address counter (RS = 0) ; - Read data from RAM (RS = 1) RW1 ; test de RS btfss octet1 , 1 goto RS0 goto RS1 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx RS0 ; Instruction Read Busy Flag & Address counter call busy ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx movf address_counter , W movwf octet_tx bank1 bsf PIE1 , TXIE ; autorisation de l'interruption d'émission de l'USART bank0 goto overrun ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx RS1 ; Instruction Read data from RAM call Read_data_from_RAM movf datas , W movwf octet_tx ; xxxxxxxxxxxxxxxxxxxxxxxx ; on teste le drapeau Busy fin_instruction1 call busy btfsc busy_flag , 0 goto fin_instruction1 ; drapeau Busy = 1 (instruction en cours) ; drapeau Busy = 0 : instruction terminée bank1 bsf PIE1 , TXIE ; autorisation de l'interruption d'émission de l'USART bank0 goto overrun ;xxxxxxxxxxxxxxxxxxxxxxxxxxxx ; test d'une erreur d'overrun overrun bank0 btfss RCSTA , OERR goto int1 ; traitement de l'erreur d'overrun ; call erreur1 bcf RCSTA , CREN ; on efface le bit OERR bsf RCSTA , CREN ; on relance la réception goto int1 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Traitement de l'interruption d'émission de l'USART ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx emission movf octet_tx , W ; les 8 bits de données à transmettre sont placés dans W bank0 movwf TXREG ; transmission ; N.B. le flag TXIF est remis à 0 par une écriture dans le registre TXREG bank1 bcf PIE1 , TXIE ; interdiction de l'interruption d'émission de l'USART bank0 goto int2 restauration swapf STATUS_TEMP,W ; restauration des registres STATUS puis W movwf STATUS swapf W_TEMP,f swapf W_TEMP,W retfie ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine ; Instruction "Read Busy Flag & Address counter" ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx busy ; étape initiale : configuration des broches RA0 à RA3 en entrées bank1 movlw B'11111111' movwf TRISA ; bit 0 du port A (RA0) = 1 : configuration en entrée (DB4) ; bit 1 du port A (RA1) = 1 : configuration en entrée (DB5) ; bit 2 du port A (RA2) = 1 : configuration en entrée (DB6) ; bit 3 du port A (RA3) = 1 : configuration en entrée (DB7) ; bits 4 à 7 du port A (RA4 à RA7) = 1 : configuration en entrée, par exemple bank0 ; 1ère étape : RS= 0, R/W =1 , E = 0 ; E=0 (RB5) ; RS = 0 (RB3) clrf PORTB_comp ; mise à jour R/W = 1 (RB4) bsf PORTB_comp , 4 movf PORTB_comp , W movwf PORTB ; mise à jour des sorties du port B ; 2ème étape : E = 1 bsf PORTB , 5 nop ; une petite pause de 200 ns ; 3ème étape : lecture DB7 (RA3)(busy flag) DB6 DB5 DB4 (address counter) btfsc PORTA , 3 bsf busy_flag , 0 btfss PORTA , 3 bcf busy_flag , 0 clrf address_counter; btfsc PORTA , 2 bsf address_counter , 6 btfss PORTA , 2 bcf address_counter , 6 btfsc PORTA , 1 bsf address_counter , 5 btfss PORTA , 1 bcf address_counter , 5 btfsc PORTA , 0 bsf address_counter , 4 btfss PORTA , 0 bcf address_counter , 4 ; 4ème étape : E = 0 bcf PORTB , 5 nop ; une petite pause de 200 ns ; 5ème étape : E = 1 bsf PORTB , 5 nop ; une petite pause de 200 ns ; 6ème étape : lecture DB3 DB2 DB1 DB0 (address counter) btfsc PORTA , 3 bsf address_counter , 3 btfss PORTA , 3 bcf address_counter , 3 btfsc PORTA , 2 bsf address_counter , 2 btfss PORTA , 2 bcf address_counter , 2 btfsc PORTA , 1 bsf address_counter , 1 btfss PORTA , 1 bcf address_counter , 1 btfsc PORTA , 0 bsf address_counter , 0 btfss PORTA , 0 bcf address_counter , 0 ; 7ème étape : E = 0 bcf PORTB , 5 nop ; une petite pause de 200 ns ; 8ème étape : R/W = 0 bcf PORTB , 4 ; dernière étape : configuration des broches RA0 à RA3 en sorties bank1 movlw B'11110000' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en sortie (DB4) ; bit 1 du port A (RA1) = 0 : configuration en sortie (DB5) ; bit 2 du port A (RA2) = 0 : configuration en sortie (DB6) ; bit 3 du port A (RA3) = 0 : configuration en sortie (DB7) ; bits 4 à 7 du port A (RA4 à RA7) = 1 : configuration en entrée, par exemple bank0 return ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; Routine ; Instruction "Read data from RAM" ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Read_data_from_RAM ; étape initiale : configuration des broches RA0 à RA3 en entrées bank1 movlw B'11111111' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en entrée (DB4) ; bit 1 du port A (RA1) = 0 : configuration en entrée (DB5) ; bit 2 du port A (RA2) = 0 : configuration en entrée (DB6) ; bit 3 du port A (RA3) = 0 : configuration en entrée (DB7) ; bits 4 à 7 du port A (RA4 à RA7) = 1 : configuration en entrée, par exemple bank0 ; 1ère étape : RS= 1, R/W =1 , E = 0 ; E=0 (RB5) clrf PORTB_comp ; mise à jour RS = 1 (RB3) bsf PORTB_comp , 3 ; mise à jour R/W = 1 (RB4) bsf PORTB_comp , 4 movf PORTB_comp , W movwf PORTB ; mise à jour des sorties du port B ; 2ème étape : E = 1 bsf PORTB , 5 nop ; une petite pause de 200 ns ; 3ème étape : lecture DB7 DB6 DB5 DB4 (datas) btfsc PORTA , 3 bsf datas , 7 btfss PORTA , 3 bcf datas , 7 btfsc PORTA , 2 bsf datas , 6 btfss PORTA , 2 bcf datas , 6 btfsc PORTA , 1 bsf datas , 5 btfss PORTA , 1 bcf datas , 5 btfsc PORTA , 0 bsf datas , 4 btfss PORTA , 0 bcf datas , 4 ; 4ème étape : E = 0 bcf PORTB , 5 nop ; une petite pause de 200 ns ; 5ème étape : E = 1 bsf PORTB , 5 nop ; une petite pause de 200 ns ; 6ème étape : lecture DB3 DB2 DB1 DB0 (address counter) btfsc PORTA , 3 bsf datas , 3 btfss PORTA , 3 bcf datas , 3 btfsc PORTA , 2 bsf datas , 2 btfss PORTA , 2 bcf datas , 2 btfsc PORTA , 1 bsf datas , 1 btfss PORTA , 1 bcf datas , 1 btfsc PORTA , 0 bsf datas , 0 btfss PORTA , 0 bcf datas , 0 ; 7ème étape : E = 0 bcf PORTB , 5 nop ; une petite pause de 200 ns ; 8ème étape : R/W = 0 bcf PORTB , 4 ; dernière étape : configuration des broches RA0 à RA3 en sorties bank1 movlw B'11110000' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en sortie (DB4) ; bit 1 du port A (RA1) = 0 : configuration en sortie (DB5) ; bit 2 du port A (RA2) = 0 : configuration en sortie (DB6) ; bit 3 du port A (RA3) = 0 : configuration en sortie (DB7) ; bits 4 à 7 du port A (RA4 à RA7) = 1 : configuration en entrée, par exemple bank0 return ;xxxxxxxxxxxxxxx ; Initialisation ;xxxxxxxxxxxxxxx initialisation bank0 clrf PORTA ; mise à 0 des sorties du port A clrf PORTB ; mise à 0 des sorties du port B movlw B'00000111' movwf CMCON ; inactivation des comparateurs analogiques bank1 movlw B'11110000' movwf TRISA ; bit 0 du port A (RA0) = 0 : configuration en sortie (DB4) ; bit 1 du port A (RA1) = 0 : configuration en sortie (DB5) ; bit 2 du port A (RA2) = 0 : configuration en sortie (DB6) ; bit 3 du port A (RA3) = 0 : configuration en sortie (DB7) ; bits 4 à 7 du port A (RA4 à RA7) = 1 : configuration en entrée, par exemple movlw B'11000111' movwf TRISB ; bit 0 du port B (RB0) = 1 : configuration en entrée, par exemple ; bit 1 du port B (RB1) = 1 : configuration en entrée (RX : USART) ; bit 2 du port B (RB2) = 1 : configuration en entrée (TX : USART) ; bit 3 du port B (RB3) = 0 : configuration en sortie (RS) ; bit 4 du port B (RB4) = 0 : configuration en sortie (R/W) ; bit 5 du port B (RB5) = 0 : configuration en sortie (E) ; bit 6 du port B (RB6) = 1 : configuration en entrée, par exemple ; bit 7 du port B (RB7) = 1 : configuration en entrée, par exemple movlw D'129' movwf SPBRG ; (SPBRG) = D'129' movlw B'00100100' movwf TXSTA ; bit 7 (CSRC) = 0 (non utilisé : 0 par exemple) ; bit 6 (TX9) = 0 : 8 bits de transmission ; bit 5 (TXEN) = 1 : autorise la réception ; bit 4 (SYNC) = 0 : mode asynchrone ; bit 3 = 0 (non implémenté) ; bit 2 (BRGH) = 1 : mode asynchrone haute vitesse ; bit 1 (TRMT) = 0 (en lecture seule) ; bit 0 (TX9D) = 0 (non utilisé : 0 par exemple) bank0 movlw B'10010000' movwf RCSTA ; bit 7 (SPEN) = 1 : utilisation du port série ; bit 6 (RX9) = 0 : 8 bits de réception ; bit 5 (SREN) = 0 (non utilisé : 0 par exemple) ; bit 4 (CREN) = 1 : autorise la réception ; bit 3 (ADEN) = 0 (non utilisé : 0 par exemple) ; bit 2 (FERR) = 0 (en lecture seule) ; bit 1 (OERR) = 0 (en lecture seule) ; bit 0 (RX9D) = 0 (non utilisé : 0 par exemple) clrf PORTA ; mise à 0 des sorties du port A clrf PORTB ; mise à 0 des sorties du port B clrf nb_octet_recu bank1 bsf INTCON, GIE ; autorisation globale des interruptions bsf INTCON , PEIE ; autorisation des interruptions des périphériques bsf PIE1 , RCIE ; autorisation de l'interruption de réception de l'USART bcf PIE1 , TXIE ; interdiction de l'interruption d'émission de l'USART bank0 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ; initialisation de l'afficheur LCD : choix du mode 4 bits ; RS R/W DB7 DB6 DB5 DB4 ; 0 0 0 0 1 0 clrf PORTB ; RS = 0 R/W = 0 E = 0 movlw B'00000010' movwf PORTA ; DB7=0 DB6=0 DB5=1 DB4=0 bsf PORTB , 5 ; E = 1 nop nop nop nop nop ; une pause de 1 µs (220 ns suffisent) bcf PORTB , 5 ; E = 0 ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx goto debut_programme ;xxxxxxxxxxxxxxxxxxxxx ; Programme principal ;xxxxxxxxxxxxxxxxxxxxx debut_programme goto debut_programme ; on attend une interruption (USART) END