Afficheur lcd 2x16 en mode 8bit pour pic 16xxx

Soyez le premier à donner votre avis sur cette source.

Vue 39 651 fois - Téléchargée 2 591 fois

Description

Voici les routines nécessaires pour faire marcher simplement un afficheur LCD en mode 8bit.

Type de pic : PIC16FXXX (ou 16CXXX)
Quartz : 4Mhz (pour utiliser un autre quartz, il suffit de modifier le fichier q4mhz.asm qui contient les routines de temporisation).

Source / Exemple :


;
;			Routines afficheur 2*16 en mode 8 Bits  	V1.0a
;
;									O.R	05/2003
;-----------------------------------------------------------------------------------------
;
;
;	LCD_INIT 		: initialisation de l'afficheur
;	LCD_WRITE_RAM_W 	: envoi un caractere ( contenu dans w ) sur l'afficheur
;	LCD_WRITE_CONTROL_W 	: envoi une commande ( contenue dans w) à l'afficheur
;	LCD_CLEAR_DISPLAY  	: efface l'afficheur
;	LCD_RETURN_HOME 	: renvoi le curseur en haut a gauche
;	LCD_LIGNE1 		: renvoi le curseur au debut de la ligne 1
;	LCD_LIGNE2 		: renvoi le curseur au debut de la ligne 2
;	LCD_ON/LCD_OFF		: allume ou eteint l'affichage
;	LCD_CURSOR_ON/LCD_CURSOR_OFF	: Affichage ou pas du curseur
;	LCD_BLINK_ON/LCD_BLINK_OFF	: Mode BLINK on ou off
;	LCD_DIR_LEFT/LCD_DIR_RIGHT	: Direction de l'écriture
;	LCD_SH_ON/LCD_SH_OFF	:
;
;	constantes a definir dans le programme principal:
;
;	LCD_DATA	; LCD: Port ou est branche le bus de donnee ( bits 0 à 7 )
;	LCD_E		; LCD: Ligne de commande de controle de l'afficheur
;	LCD_RW		; LCD: Ligne de Lecture/Ecriture de l'afficheur
;	LCD_RS		; LCD: Ligne de selection de l'afficheur
;
;	variables a definir dans le programme principal:
;
;       LCD_mode_set, LCD_disp_cont,DATA_TMP,J    		       
;       LCD_curs_disp_shift, LCD_func_set
;

LCD_INIT:			;Initialisation de l'afficheur

	CALL	Tempo_30ms
	movlw	LCD_FUNCTION_SET	;Function set
	movwf	LCD_func_set		;Sauvegarde des paramètres
	call 	LCD_WRITE_CONTROL_W	;Ecriture
	               			;Tempo de 39us

	movlw	LCD_DISPLAY_CONTROL	;Display ON/OFF
	movwf	LCD_disp_cont		;Sauvegarde des paramètres
	call 	LCD_WRITE_CONTROL_W	;Ecriture
					;Tempo de 39us

	call 	LCD_CLEAR_DISPLAY

	movlw	LCD_ENTRY_MODE_SET	;Entry mode set
	movwf	LCD_mode_set		;Sauvegarde des paramètres
	call 	LCD_WRITE_CONTROL_W	;Ecriture
 	CALL	Tempo_43us

	movlw	LCD_CURSOR_DISPLAY_SHIFT
	movwf	LCD_curs_disp_shift	;Sauvegarde des paramètres

	return				;Init end

LCD_WRITE_CONTROL_W:
	bcf	LCD_RW			;Write
	bcf	LCD_RS			;RS a 0
	bsf	LCD_E			;Enable a 1
	movwf	LCD_DATA		;Copie W sur le bus DATA
	bcf	LCD_E			;Enable a 0
 	CALL	Tempo_43us
	return

LCD_WRITE_RAM_W:
	bcf	LCD_RW			;Write
	bsf	LCD_RS			;RS a 1
	bsf	LCD_E			;Enable a 1
	movwf	LCD_DATA		;Copie W sur le bus DATA
	bcf	LCD_E			;Enable a 0
 	CALL	Tempo_43us
	return

LCD_SET_CGRAM_ADD:
	movlw	h'40'
	bcf	LCD_RW			;Write
	bcf	LCD_RS			;RS a 0
	bsf	LCD_E			;Enable a 1
	movwf	LCD_DATA		;Copie W sur le bus DATA
	bcf	LCD_E			;Enable a 0
 	CALL	Tempo_43us
	return

LCD_SET_DDRAM_ADD:
	movlw	h'80'
	bcf	LCD_RW			;Write
	bcf	LCD_RS			;RS a 0
	bsf	LCD_E			;Enable a 1
	movwf	LCD_DATA		;Copie W sur le bus DATA
	bcf	LCD_E			;Enable a 0
 	CALL	Tempo_43us
	return

LCD_LIGNE1:
	movlw	h'80'
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_LIGNE2:
	movlw	h'C0'
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_CLEAR_DISPLAY:
	movlw	h'01'
 	CALL	LCD_WRITE_CONTROL_W
 	CALL	Tempo_1530us
	return

LCD_RETURN_HOME:
	movlw	h'02'
 	CALL	LCD_WRITE_CONTROL_W
 	CALL	Tempo_1530us
	return

LCD_ON:
	bsf  	LCD_disp_cont,2		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_OFF:
	bcf  	LCD_disp_cont,2		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_CURSOR_ON:
	bsf  	LCD_disp_cont,1		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_CURSOR_OFF:
	bcf  	LCD_disp_cont,1		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_BLINK_ON:
	bsf  	LCD_disp_cont,0		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_BLINK_OFF:
	bcf  	LCD_disp_cont,0		
	movf	LCD_disp_cont,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_DIR_LEFT:
	bcf  	LCD_mode_set,1		
	movf	LCD_mode_set,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_DIR_RIGHT:
	bsf  	LCD_mode_set,1		
	movf	LCD_mode_set,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_SH_ON:
	bsf  	LCD_mode_set,2		
	movf	LCD_mode_set,0
 	CALL	LCD_WRITE_CONTROL_W
	return

LCD_SH_OFF:
	bcf  	LCD_mode_set,2		
	movf	LCD_mode_set,0
 	CALL	LCD_WRITE_CONTROL_W
	return

Conclusion :


Première étape indispensable : passer par un call LCD_INIT pour initialiser l'écran.
Ensuite pour écrire un caractère, rien de plus simple :

movlw d'41' (A en ascii)
call LCD_WRITE_RAM_W

et c tout !

le fichier lcd_8b.inc contient toutes les données d'initialisations.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

CHECK_BUSY: ; ATTENTION: Sur les CPU rapides (quartz 20 MHz) il faut tenir compte du "Hold time" de l'afficheur (environ 500 ns). Dans ce cas rajouter 2 NOP dans le doute.
BCF STATUS,RP1 ; Si on ne travaille autour qu'avec les deux premières banques, cette ligne peut etre supprimée
BSF STATUS,RP0 ; On passe en banque 1 pour TRISx
MOVLW b'11111111'
MOVWF LCD_DATA_TRIS ; On passe en entrée le port LCD_DATA ENTIER.
BCF STATUS,RP0 ; On passe en banque 0
BCF LCD_RS ; RS a 0
BSF LCD_RW ; LCD en lecture
BSF LCD_E
TEST_BUSY:
BTFSC LCD_DATA,7 ; On vérifie si le bit busy est à 1 (occupé)
GOTO TEST_BUSY ; Occupé? On re-teste...
BCF LCD_E ; L'afficheur n'est plus occupé: Enable a 0
BCF LCD_RW ; LCD en écriture comme d'hab
BSF STATUS,RP0 ; On passe en banque 1 pour TRISx
CLRF LCD_DATA_TRIS ; On remet le port LCD_DATA en sortie
BCF STATUS,RP0 ; On repasse finalement en banque 0 (tout le reste est en banque 0 de toutes facons)
RETURN ; on rend la main


La mise en page va surement être crado (la zone commentaire oblige), mais ceci est un code qui permet de se passer de la plupart des temporisations d'afficheur. Il lit le Busy Flag (broche 7 de l'afficheur), qui passe a zéro quand ce dernier est apte à recevoir la suite. Ca permet de faire éventuellement autre chose en attendant plutôt que de tourner dans des boucles d'attente.

On mettra un CALL CHECK_BUSY avant d'envoyer des trucs à l'afficheur, et le tour est joué.
En fonction de l'endroit où on incorpore cette routine, il sera peut-être nécessaire de sauvegarder W dans une variable, et de la restaurer juste avant le RETURN. En effet cette routine a elle-même besoin de W.
ATTENTION: lors de la phase d'initialisation (ta routine LCD_INIT), il n'est pas encore possible à ce stade, de se servir du Busy Flag: ici il faut passer par des temporisations, il n'y a pas le choix.

J'ai changé de banque directement avec des BCF/BSF. Si on met des BANKSEL, c'est plus évident mais cette ligne est digérée par le compilateur et est remplacé par DEUX LIGNES à chaque fois, au total ça en fera 2 de trop.
Ne pas oublier un petit:
LCD_DATA_TRIS equ TRISx (x étant le port sur lequel se trouve les lignes de données du LCD) sinon ca foire, évidemment.

Voilàvoilà.
J'ai du mal à comprendre comment des lignes vides (ligne 39 et ligne 45) peuvent faite des "tempo de 39 microsecondes", dixit le commentaire de ces mêmes lignes.

De plus, tu indiques en commentaire ligne 30, les "variables à définir dans le programme principal", deux variables qui ne sont pas utilisés du tout dans ton code: DATA_TMP et J.

Ligne 38, 43, 50, 55 (commentés 'sauvegarde des paramètres'): je ne vois pas bien l'intérêt: ces variables ne sont jamais réutilisées (sauf erreur de ma part).

Bref, j'avoue ne pas avoir testé ton code, sans vouloir te vexer, j'ai de gros doutes sur la qualité de ton travail.
Messages postés
39
Date d'inscription
mardi 2 septembre 2003
Statut
Membre
Dernière intervention
7 décembre 2006

Bonjour tranqilos,
Voila, je ne connais rien en matiere d'asm. Aussi, pourriez vous ajouter à vos informations les cyclogrammes que vous avez utilises en reference ? La notation qui vous a ete attribuee temoigne d'une excellente prestation dont je vous felicite et qui vous vaut mon admiration !
A partir de cette information, je pourrais tenter, avec votre permission, de reprendre mes sources c pour "coller" a ce qui vous avez realise.
En effet, je viens de realiser sur un PIC18F458 une surveillance de vitesse utilisant les donnees GPS de la trame NMIA. Je voudrais rajouter l'affichage en clair des vitesses (consigne et actuelle) ainsi que, pour le plaisir, la position geographique. Mais j'ai beaucoup de deboires avec ces damnes timings et la sequence lcd_init() ne se realise jamais !!! En vous remerciant, bien cordiales salutations, radioham
Messages postés
483
Date d'inscription
mardi 10 juillet 2001
Statut
Membre
Dernière intervention
12 juillet 2006

euhmm... la fréquence du pic doit être de cmb car tu utlise un tempo de 40 ms mais ça dépend du quartz.. tuarais du préciser.. sinon c pas mal !
A+

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.