Upload
magali-fievet
View
107
Download
1
Embed Size (px)
Citation preview
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 1
Driver de port parallèle
Commande d’un module
d’affichage LCD
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 2
Objectif du chapitre
• Faire fonctionner un module d’affichage LCD couplé sur le port parallèle de la cible CEPC
– Étude sommaire du port parallèle standard des PC– Étude sommaire du module LCD– Écriture d’un driver pour ce module– Écriture d’une application pour afficher deux lignes
sur le module LCD– Téléchargement dans le CEPC– Exécution
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 3
Port Parallèle d’un PC (1)
• Le port parallèle standard (SPP) est un port prévu dès l’origine du PC pour obtenir une liaison plus rapide que la liaison série de l’époque, utile pour commander une imprimante
• Dans un PC-XT ou dans un PC-AT le SPP n’était pas sur la carte mère mais sur une carte additionnelle qui contenait aussi un port série
• Carte à installer dans un connecteur du bus ISA
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 4
Port Parallèle d’un PC (2)
• Il était possible d’installer sur le bus ISA deux cartes série/parallèle en choisissant par des straps deux décodages d’adresse possibles
– 0x378 : Parallel Printer 1 (LPT1) associé à l’IRQ7– 0x278 : Parallel Printer 2 associé à l’IRQ5
• Cet adaptateur parallèle n’était même pas un boîtier spécifique mais l’association d’un PAL et de quelques latches et drivers constituant trois registres
• Plus tard sont apparus des circuits spécifiques plus polyvalents
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 5
Port Parallèle d’un PC (3)
• Registre de données (D0-D7) – à l’adresse de base du port
• Registre de Status (S3-S7)– à l’adresse de base du port + 1– utilisé pour ses cinq bits de poids forts seulement
S3-S7, S0-S2 inutilisés ou inexistants
• Registre de commande (C0-C4)– à l’adresse de base du port + 2– Utilisé pour ses cinq bits de poids faibles C0-C4, C5-
C7 inutilisés ou inexistants– ici nous n’utilisons que C0-C4
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 6
Registres du port parallèle
Adresse de base
Registre de données
D7 D0
Adresse de base + 1
Registre de status (lecture)
S7
Adresse de base + 2
Registre de contrôle
C0
Poids fort Poids faible
S5S6 S4 S3
C3 C2 C1
D6 D5 D4 D3 D2 D1
C4
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 7
Registres données et commande
D0 D0
D1
D2
D3
D4
D5
D6
D7
Registre données Buffer
D5
D2
D3
D4
D1
D6
D7
C0 C0
C1
C2
C3
Registre commande Buffer
C2
C3
C1
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 8
Registre status
• Inutilisé dans notre application
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 9
Écriture sur un port
VOID WRITE_PORT_UCHAR(PUCHAR Port, UCHAR Value);
Parameters
Port
[in] Pointer to the port that must be a mapped memory range in I/O space.
Value
[in] Byte to be written to the port.
Return Values
None.
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 10
Module d’affichage LCD HD44780
• Le module possède– Une mémoire de 80 caractères :
Display Data RAM (DD RAM)– Un générateur de police de caractère– Deux registres internes DR et IR
• Taille de l’afficheur utilisé :– Nombre de lignes d’affichage : 2– Nombre de caractères par ligne : 20
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 11
Signaux du module LCD
• Port de données D0-D7• RS Register Select• E Enable• R/W Lecture/écriture, pour nous 0, écriture
• VDD Alimentation, pour nous sera prise sur le port sur la broche C2
• VSS Masse
• VL Contrôle du contraste, pour nous 0,contraste maximal
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 12
Câblage du module LCD sur le port parallèle
Module d’affichage LCD
R/W VSS VL VDD
Port parallèle
D7 D6 D5 D4 D3 D2 D1 D0
D7 D6 D5 D4 D3 D2 D1 D0
RS E
C0C3
VDD VDD
VDD
9 8 67 5 34 172 1
VL à la masse donne le contraste
maximum
10 KΩ 10 KΩ
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 13
Registres internes du module LCD
• Deux registres internes– IR registre d’instruction– DR registre de données
• Commande des registres par deux signaux– RS : Register Selector relié à la broche C3 du port
parallèle différencie ces deux registres– E : Enable relié à la broche C0 du port parallèle
valide l’introduction des données dans les registres
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 14
Séquence d’écriture dans IR et DR
R SIR sé le c té
D R sé le c té
D 0 - D 7 D a ta p o u r IR D a ta p o u r D R
ED a ta p ris e e n c o m p te
Repos IR
RS=0 E=0
Donnée → IR
RS=0 E→0Donnée → DR
RS=1 E→0
Repos DR
RS=1 E=0
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 15
Commandes pour écrire IR
• Signaux de commande en position de repos RS relié à C3 et E relié à C0 mais C3 et
C0 sont complémentées d’où : commande . . . . 1 x x 1 (RS=0 E=0)
• Mettre l’instruction sur le port parallèle D0-D7• Écrire cette instruction dans le registre IR
commande . . . . 1 x x 0 (RS=0 E=1)• Retour à l’état de repos
commande . . . . 1 x x 1 (RS=0 E=0)
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 16
Commandes pour écrire DR
• Signaux de commande en position de repos RS relié à C3 et E relié à C0 mais C3 et
C0 sont complémentées d’où : commande . . . . 0 x x 1 (RS=1 E=0)
• Mettre la donnée sur le port parallèle D0-D7• Écrire cette donnée dans le registre DR
commande . . . . 1 x x 0 (RS=1 E=1)• Retour à l’état de repos
commande . . . . 1 x x 1 (RS=1 E=0)
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 17
Options
• On peut commander la tension VDD avec la ligne C2, ce qui évite une alimentation externe
• La ligne C1 est réservée pour avoir un second signal Enable utilisé avec un afficheur à 4 lignes
C2
1N4148
VDD
1 µF+
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 18
Détail des commandes IR et DR
• Afficheur LCD à deux lignes → C1 inutilisé, à 0 Alimentation par le port → C2 toujours à 1
• Repos en prévision d’une commande pour IR%1101 = 0xD «CTRL» C2=1 RS=0 E=0
• Entrée de la commande dans IR%1100 = 0xC «CTRLEN» C2=1 RS=0 E=1
• Repos en prévision d’une commande pour DR%0101 = 0x5 «DATA» C2=1 RS=1 E=0
• Entrée de la commande dans DR%0100 = 0x4 «DATAEN» C2=1 RS=1 E=1
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 19
DDRAM du module LCD
• Le module LCD contient une DDRAM gérée automatiquement par les écritures dans le registre DR
• La donnée écrite dans le registre DR est transférée systématiquement dans la DDRAM à une adresse définie par un compteur d’adresse interne (AC)
• AC incrémenté à chaque écriture dans DR• AC initialisé par écriture de l’instruction
Set DDRAM address dans le registre IR
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 20
LCD à 2 lignes de 20 caractères
DDRAM
20 caractères
20 caractères
20 caractères
20 caractères
Premièreligne
Secondeligne
0x00
0x270x40
0x67
0x13
0x530x54
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 21
Instructions pour le LCD (1)
• Clear Display: 0x01• Return Home: 0x02• Entry Mode Set: 0x04 à 0x07 (%000001 I/D S)
– I/D = 1 incrément– S = 0 pas de décalage
• Display ON/OFF: 0x08 à 0x0F (%00001 D C B)– D = 0 display OFF– C = 0 cursor OFF– B = 0 blink OFF
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 22
Instructions pour le LCD (2)
• Function Set: 0x38 pour nous (%001 DL N F 00)– DL=1 Interface 8 bits– N=0 LCD à deux lignes (0 pour une ligne)– F=0 Matrice 5x7
• Set DDRAM address: 0x80 à 0xFF (%1AAAAAAA)
– AAAAAAA Adresse à placer dans le compteur AC
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 23
Initialisation du LCD
• Timing à respecter après la mise sous tension
• Séquence de commande obligatoire de configuration du LCD
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 24
Timing à respecter après Power On
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 25
Séquence d’initialisation
• RESET:Instruction 0x30 (Function Set: interface 8 bits) envoyée 3 fois
• Display OFF• Display ON• Clear Display• Function Set: taille de l’interface, nombre de
lignes et police. (non modifiable ensuite)• Mode Set: gestion affichage (décalage texte,
incrément d’adresse mémoire)
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 26
Exemple d’envoi de commande
// Mise du port dans l’état repos commande
WRITE_PORT_UCHAR(PARCOMMAND,CTRL);
Sleep(15); // Attente de 15ms après la mise sous tension
// Function Set 1 (interface 8 bits)
WRITE_PORT_UCHAR(PARDATA,0x30);
WRITE_PORT_UCHAR(PARCOMMAND, CTRLEN);
Sleep(2); // Attente de 2 ms
WRITE_PORT_UCHAR(PARCOMMAND, CTRL);
Sleep(5); // Attente de 5 ms
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 27
Travail à réaliser
• Préparer une plate-forme• Préparer un driver à inclure• Générer le noyau avec le driver• Préparer une application• Générer l’application sans l’inclure avec le
noyau• Télécharger le noyau dans la cible• Exécuter l’application
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 28
Driver
• Le driver comprendra deux IOCTL– Écriture d’un caractère– Positionnement du curseur
• On définira un projet PARA_DRV de type WCE Dynamic Link Library à inclure dans le noyau
• On créera un fichier PARA.def que l’on inclura dans le projet PARA_DRV
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 29
Application
• L’application– écrira un texte sur la ligne 1 du LCD– puis positionnera le curseur en début de ligne 2– écrira un deuxième texte sur la ligne 2
• On définira l’application PARA_APP de type WCE Application à ne pas inclure dans le noyau
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 30
Driver
Corrigé
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 31
PARA.def
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 32
Driver (1)
// #include nécessaires
#include "stdafx.h"
#include <tchar.h>
#include <nkintr.h>
#include <wdm.h>
#include <windev.h>
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 33
Driver (2)
// Définition des IOCTL
#define IOCTL_PUTC \ CTL_CODE(FILE_DEVICE_UNKNOWN,2048,\ METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_CURSEUR \ CTL_CODE(FILE_DEVICE_UNKNOWN,2049,\
METHOD_BUFFERED,FILE_ANY_ACCESS)
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 34
Driver (3)
// Définition des adresses du port parallèle
#define PARBASE ((PUCHAR) 0x0378)
#define PARDATA PARBASE
#define PARCOMMAND PARBASE+2
// Définition des mots de commande
#define CTRL 0xD
#define CTRLEN 0xC
#define DATA 0x5
#define DATAEN 0x4
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 35
Driver (4)
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 36
Driver (5)
DWORD PAR_Init(DWORD dwContext){
DWORD dwRet = 1;RETAILMSG(1,(TEXT("PARA_DRV: PAR_Init\n")));
// Mise du port dans l’état repos commandeWRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(15);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 37
Driver (6)
// Envoi des trois Function Set de RESET
// Positionnement de la donnée : 0x30WRITE_PORT_UCHAR(PARDATA,0x30);
// Function Set 1 WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(5);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 38
Driver (7)
// Function Set 2WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(1);
// Function Set 3WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(10);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 39
Driver (8)
// Display OFFWRITE_PORT_UCHAR(PARDATA,0x08);WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(10);// Display ONWRITE_PORT_UCHAR(PARDATA,0x0F);WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(10);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 40
Driver (9)
// Clear DisplayWRITE_PORT_UCHAR(PARDATA,0x01);WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL); Sleep(10);// Function Set (2 lignes, 8 bits)WRITE_PORT_UCHAR(PARDATA,0x38);WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL);Sleep(10);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 41
Driver (10)
// Mode Set (incrément, pas de décalage)WRITE_PORT_UCHAR(PARDATA ,0x06);WRITE_PORT_UCHAR(PARCOMMAND,CTRLEN);Sleep(2);WRITE_PORT_UCHAR(PARCOMMAND,CTRL); Sleep(10);// Mise du port dans l’état repos dataWRITE_PORT_UCHAR(PARCOMMAND,DATA);
return dwRet;}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 42
Driver (11)
BOOL PAR_Deinit(DWORD hDeviceContext)
{
BOOL bRet = TRUE;
RETAILMSG(1,(TEXT("PARA_DRV: PAR_Deinit\n")));
return bRet;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 43
Driver (12)
DWORD PAR_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
DWORD dwRet = 1;
RETAILMSG(1,(TEXT("PARA_DRV: PAR_Open\n")));
return dwRet;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 44
Driver (13)
BOOL PAR_Close(DWORD hOpenContext)
{
BOOL bRet = TRUE;
RETAILMSG(1,(TEXT("PARA_DRV: PAR_Close\n")));
return bRet;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 45
Driver (14)
BOOL PAR_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut){
int val; BOOL bRet;
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 46
Driver (15)
switch(dwCode)
{
case IOCTL_PUTC:
WRITE_PORT_UCHAR(PARDATA,pBufIn[0]);
WRITE_PORT_UCHAR(PARCOMMAND, DATAEN);
Sleep(2);
WRITE_PORT_UCHAR(PARCOMMAND,DATA);
break;
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 47
Driver (16)
case IOCTL_CURSEUR:
// Positionnement du curseur
val=pBufIn[0];
// Commande 1xxxxxxx (xxxxxxx position curseur)
val=val+0x80;
// Mise du port en repos commande
WRITE_PORT_UCHAR(PARCOMMAND,CTRL);
Sleep(2);
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 48
Driver (17)
// Envoi de la commande de positionnement
WRITE_PORT_UCHAR(PARDATA,val); WRITE_PORT_UCHAR(PARCOMMAND,
CTRLEN);
Sleep(2);
WRITE_PORT_UCHAR(PARCOMMAND,CTRL);
// Mise du port en repos data
WRITE_PORT_UCHAR(PARCOMMAND,DATA);
break;
}// switch
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 49
Driver (18)
*pdwActualOut=1;
return bRet;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 50
Application
Corrigé
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 51
Application (1)
// #include nécessaires
#include "stdafx.h"
#include <windev.h>
// Définition des IOCTL
#define IOCTL_PUTC \ CTL_CODE(FILE_DEVICE_UNKNOWN,2048,\ METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_CURSEUR \ CTL_CODE(FILE_DEVICE_UNKNOWN,2049,\
METHOD_BUFFERED,FILE_ANY_ACCESS)
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 52
Application (2)
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 53
Application (3)
// Déclarations et réservations
HANDLE hDevice;
CHAR carac1[1];
DWORD dwNb;
HANDLE hPara;
CHAR* pstring1 = "essai port parallèle\n";
CHAR* pstring2 = "miracle ca marche\n";
unsigned int i;
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 54
Application (4)
// Chargement du driver
hDevice=RegisterDevice(TEXT("PAR"),1,
TEXT("PARA_DRV.dll"),NULL);
if(hDevice==0)
{
MessageBox(NULL,_T("Pb Register PAR1:"),
_T("PARA_APP"),MB_OK);
return 0;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 55
Application (5)
// Ouverture du driverhPara=CreateFile(TEXT("PAR1:"),GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,0);
if(hPara==INVALID_HANDLE_VALUE) { MessageBox(NULL,_T("Pb Ouverture PAR1:"), _T("PARA_APP"),MB_OK); DeregisterDevice(hDevice);
CloseHandle(hDevice); return 0;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 56
Application (6)
// Envoi première chaîne
for(i=0;i<strlen(pstring1);i++)
{
carac1[0]=pstring1[i];
DeviceIoControl(hPara,IOCTL_PUTC,carac1,1,
carac1,1,&dwNb,NULL);
Sleep(10);
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 57
Application (7)
// Positionnement du curseur au début de la ligne 2carac1[0]=0x40;DeviceIoControl(hPara,IOCTL_CURSEUR,
carac1,1,carac1,1,&dwNb,NULL);// Envoi deuxième chaînefor(i=0;i<strlen(pstring2);i++){
carac1[0]=pstring2[i];DeviceIoControl(hPara,IOCTL_PUTC,carac1,1,
carac1,1,&dwNb,NULL);Sleep(10);
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 58
Application (8)
// Fermeture des handles
CloseHandle(hPara);
DeregisterDevice(hDevice);
CloseHandle(hDevice);
MessageBox(NULL,_T("Fin application PARA_APP"),
_T("PARA_APP"),MB_OK);
return 0;
}
jc/md/lp-01/05
Module d'affichage LCD sur le port parallèle : corrigé 59
Conclusion
• Nous avons construit un driver et une application rudimentaires pour commander un module d’affichage LCD installé sur un port parallèle standard de PC.