Bonjour,
Je suis actuellement en train de travailler sur un décodeur DTMF et mon problème est le suivant :
Je veux tout d'abord afficher, avec mon LCD, une lettre sur mon afficheur.
J'ai avant tout déjà testé mon PIC pour voir si les connections se faisaient avec un petit programme pour allumer la diode et ceci marché sans problème. Mes connections se font bien sur l'afficheur donc ça ne peut provenir que du programme qui est le suivant :
LCD.c
#include <p18f2550.h>
#include "LCD4bits.h"
#include <delays.h>
#pragma config WDT = OFF
void main (void)
{
/* PORTB RB0,RB1,RB2,RB3 sortie, pour l'afficheur */
TRISBbits.TRISB0 = 0;
TRISBbits.TRISB1 = 0;
TRISBbits.TRISB2 = 0;
TRISBbits.TRISB3 = 0;
Delay100TCYx (2);
TRISCbits.TRISC0 = 0;
TRISCbits.TRISC1 = 0;
TRISCbits.TRISC2 = 0;
init_lcd (0);
aff_car ('A');
}
Serait-il possible d'avoir un avis sur ce code et si possible une aide afin de règler ce problème ?LCD.h
/*============================= ============================== ========================*/
#include <delays.h>
#ifndef LCD4BITS_H //facultatif (mais il faut faire attention de ne pas inclure
#define LCD4BITS_H //le même .h plus d'une fois dans un projet).
typedef unsigned char byte; //facultatif pour Code Warrior.
typedef unsigned int word; //Idem.
typedef unsigned long dword; //Idem.
/****************************** ****************************** *************************/
/* Déclaration d'un champ de bits */
union {
struct { //une structure 8 bits (champ de bits).
byte bit0:1,
bit1:1,
bit2:1,
bit3:1,
bit4:1,
bit5:1,
bit6:1,
bit7:1;
}bits;
byte octet; //un byte (octet).
} mon_octet ; //accès à l'octet complet par mon_octet.octet et
//accès aux bits par mon_octet.bits.bitx .
/****************************** ****************************** *************************/
/* Définition des broches utilisées */
//bits de données du LCD = utilisation des 4 broches du micro au choix:
#define DATA4 PORTBbits.RB0 //bit 3 du PORTB ou toute autre broche.
#define DATA5 PORTBbits.RB1 //bit 4 du PORTB ou toute autre broche.
#define DATA6 PORTBbits.RB2 //bit 5 du PORTB ou toute autre broche.
#define DATA7 PORTBbits.RB3 //bit 6 du PORTB ou toute autre broche.
//bits de direction des broches de données:
#define DDR_DATA4 TRISBbits.TRISB0 // bit de direction de la broche PTB_PTB3.
#define DDR_DATA5 TRISBbits.TRISB1
#define DDR_DATA6 TRISBbits.TRISB2
#define DDR_DATA7 TRISBbits.TRISB3
//bits de commande du LCD = utilisation des 3 broches du micro au choix:
#define LCD_RS PORTCbits.RC1 //LCD_RS = bit 0 du PORTB ou toute autre broche.
#define LCD_RW PORTCbits.RC2 //LCD_RW = bit 1 du PORTB ou toute autre broche.
#define LCD_E PORTCbits.RC0 //LCD_E = bit 2 du PORTB ou toute autre broche.
//bits de direction des broches de commande:
#define DDR_LCD_RS TRISCbits.TRISC1 // bit de direction de la broche PTB_PTB0.
#define DDR_LCD_RW TRISCbits.TRISC2
#define DDR_LCD_E TRISCbits.TRISC0
/* Déclaration des fonctions élaborées */
void ecr_ctrl(byte ctrl);
void ecr_data(byte data);
void busy_lcd(void);
void init_lcd(byte curseur);
void xy_lcd(byte x, byte y);
void aff_car(byte c);
void aff_txt(byte *message);
void efface_lcd(void);
void defini_cars(const byte *c, byte char_code);
void onoff_lcd(byte onoff);
void aff_base(dword hexa, byte base);
void aff_float(float data, byte decimale);
void aff_CAN(byte CAN, byte decimal);
void aff_heure(byte heures, byte minutes, byte secondes);
/* Temporisation logicielle: */
void tempo_ms(word temps);
//****************************** ****************************** *************************
const byte *h="0123456789ABCDEF";
//****************************** ****************************** *************************
//#include "car_spec.h" //table définissant quelques caractères spéciaux.
/****************************** ****************************** **************************
void ecr_ctrl(byte ctrl)
****************************** ****************************** **************************/
void ecr_ctrl(byte ctrl){
//utilise la variable mon_octet.octet pour avoir accès aux bits de ctrl :
mon_octet.octet=ctrl;
//met d'abord les 4 bits de poids forts de ctrl sur les 4 lignes DATA 7-4 utilisées du LCD
//(mode 4 bits)
PORTB = ( ( ctrl >> 4 ) & 0x0F );
LCD_RS=0; //envoie un octet de commande.
LCD_RW=0; //écriture dans la RAM du LCD.
LCD_E=1; //validation par l'impulsion E.
LCD_E=0;
//met par la suite les 4 bits de poids faible de ctrl sur les 4 lignes DATA 7-4
//utilisées du LCD (mode 4 bits)
PORTB = ( ctrl & 0x0F );
LCD_E=1; //validation par l'impulsion E.
LCD_E=0;
//test du bit Busy ou attente de #2ms pour que le LCD soit prêt.
busy_lcd();
}
/****************************** ****************************** **************************
void ecr_data(byte data)
Envoie un octet de donnée data dans la RAM du LCD.
****************************** ****************************** **************************/
void ecr_data(byte data){
//utilise la variable mon_octet.octet pour avoir accès aux bits de data.
mon_octet.octet=data;
//met d'abord les 4 bits de poids forts de data sur les 4 lignes DATA 7-4 utilisées du
//LCD (mode 4 bits)
PORTB = ( ( data >> 4 ) & 0x0F );
LCD_RS=1; //envoie un octet de donnée.
LCD_RW=0; //écriture dans la RAM du LCD.
LCD_E=1; //validation par l'impulsion E.
LCD_E=0;
//met par la suite les 4 bits de poids faible de ctrl sur les 4 lignes DATA 7-4
//utilisées du LCD (mode 4 bits)
PORTB = ( data & 0x0F );
LCD_E=1; //validation par l'impulsion E.
LCD_E=0;
//test du bit Busy ou attente de #2ms pour que le LCD soit prêt.
busy_lcd();
}
/****************************** ****************************** **************************
busy_lcd(void)
****************************** ****************************** **************************/
void busy_lcd(void){
int i;
for (i = 0; i < 5000; i++)
;
}
/****************************** ****************************** **************************
void init_lcd(byte curseur)
Initialise le LCD et les PORTs utilisés.
void init_lcd(byte curseur){
//initialise les 4 lignes DATA 7-4 du micro utilisé en sortie.
// DDR_DATA4=1;
// DDR_DATA5=1;
// DDR_DATA6=1;
// DDR_DATA7=1;
//initialise les broches de contrôle du LCD en sortie.
// DDR_LCD_RS=1;
// DDR_LCD_E=1;
// DDR_LCD_RW=1;
busy_lcd(); //test du bit Busy ou attente de #50ms pour que le LCD soit prêt.
ecr_ctrl(0x28); //adressage 4 Bits, afficheur 2 lignes.
ecr_ctrl(0x06); //incrémente l'adresse DD-RAM (l'affichage se décale vers la
//droite).
ecr_ctrl(0x01); //effacement de l'écran et curseur positionné en haut à gauche.
switch(curseur){
case 0:
ecr_ctrl(0x0C); //curseur hors service, affichage actif.
break;
case 1:
ecr_ctrl(0x0E); //curseur en service, affichage actif.
break;
case 2:
ecr_ctrl(0x0F); //curseur clignotant en service.
break;
default:
break;
};
}
/****************************** ****************************** **************************
void xy_lcd(byte x, byte y)
Positionne le curseur aux coordonnées (x, y) : 1 <= x <= 16 et 1 <= y <= 2.
****************************** ****************************** **************************/
void xy_lcd(byte x, byte y){
if (y==1)
ecr_ctrl(0x80+x-1); //positionne la ligne 1 aux coordonnées (x, 1).
if (y==2)
ecr_ctrl(0xC0+x-1); //positionne la ligne 2 aux coordonnées (x, 2).
}
/****************************** ****************************** **************************
void aff_car(byte c)
Affiche à la position du curseur le caractère dont le code ascii est c.
****************************** ****************************** **************************/
void aff_car(byte c){
ecr_data (c);
}
/****************************** ****************************** **************************
void aff_txt(byte *message)
Affiche, à la position du curseur, le texte " message ".
****************************** ****************************** **************************/
void aff_txt(byte *message){
while(*message!= '\0'){ //écriture sur le LCD de toute la chaîne.
if(*message=='\r')
xy_lcd(1,2);
else
aff_car(*message); //écriture sur le LCD d'un caractère du message.
message++;
};
}
/****************************** ****************************** **************************
void efface_lcd(void)
Efface l'écran et positionne le curseur en haut à gauche.
****************************** ****************************** **************************/
void efface_lcd(void){
ecr_ctrl(0x01);
}
/****************************** ****************************** **************************
void defini_cars(const byte *c, char_code)
****************************** ****************************** **************************/
void defini_cars(const byte *c, byte char_code){
byte i=0,a;
a=(char_code<<3)|0x40; //les caractères sont logés dans le CGRAM du LCD à partir
//de l'adresse 0x40.
for(i=0; i<8; i++){
ecr_ctrl(a);
ecr_data(c[i]);
a++;
};
}
/****************************** ****************************** **************************
void onoff_lcd(byte onoff)
****************************** ****************************** **************************/
void onoff_lcd(byte onoff){
if(onoff==1)
ecr_ctrl(0x0C);
else
ecr_ctrl(0x08);
}
/****************************** ****************************** **************************
void aff_base(dword hexa, byte base)
Affiche, sur le LCD, hexa en base : 2 (binaire) <= base <= 16 (hexadécimale).
****************************** ****************************** **************************/
void aff_base(dword hexa, byte base){
byte i=0; //compteur.
static byte buf[32]; //buffer de stockage; static car il est appelé de la
//fonction aff_float juste après.
/* remplit buf[i] par le code ascii du résultat de l'opération (hexa%base)
(cf constante *h déclarée en entête). */
do{
buf[i]=h[hexa%base]; //conversion Hexa/ASCII de la fin vers le début.
hexa=hexa/base;
i++;
}while(hexa);
/* affiche le contenu du buffer, de la fin vers le début et caractère par
caractère, directement dans la RAM du LCD. */
do{
i--;
aff_car(buf[i]);
} while(i>0);
}
/****************************** ****************************** **************************
void aff_float(float data, byte decimal)
Convertit, arrondit et affiche, à la position du curseur, data (type float 32 bits) au
format décimal avec 1 à 6 décimales.
****************************** ****************************** **************************/
void aff_float(float data, byte decimal){
byte i;
dword dec, dec10=10;
if(data<0){
aff_car('-'); //si data est négatif affiche '-'.
data*=-1; //data est rendu positif.
}
for(i=0; i< decimal; i++) //dec10=10^(decimal+1).
dec10*=10;
dec=dec10*(data-(dword)data);//partie décimale, à (decimal+1) chiffres, est rangé dans dec,
if(dec%10>=5) //puis arrondis à la valeur supérieure.
dec+=10;
if(dec > dec10-1){ //si Overflow,
data +=1; //ajoute 1 à la partie entière,
dec=0; //et la partie décimale est mise à 0.
}
aff_base(data, 10); //tronque data et affiche la partie entière.
if(decimal !=0){
aff_car('.');
dec10/=100; //dec10=10^(decimal-1).
dec=dec/10; //dec est à decimal chiffres.
while(dec/dec10==0 && decimal>1){
aff_car('0'); //affiche les éventuels zéros à gauche de la
//partie décimale.
dec10/=10;
decimal--;
}
aff_base(dec, 10); //affiche le reste de la partie décimale.
}
}
/****************************** ****************************** **************************
void aff_CAN(byte CAN, byte decimal)
Le résultat (CAN) de la conversion A/N, issu du CAN du micro, est converti en tension et
inscrit dans la RAM d'affichage du LCD.
****************************** ****************************** **************************/
void aff_CAN(byte CAN, byte decimal){
aff_float(5.0*CAN/255, decimal); //plein d'échelle = 5 volts et résolution = 8 bits.
aff_txt(" V"); //affiche l'unité de mesure.
}
/****************************** ****************************** **************************
void aff_heure(byte heures, byte minutes, byte secondes)
Affiche à la position du curseur l'heure, sous la forme HH:MM:SS.
****************************** ****************************** **************************/
void aff_heure(byte heures, byte minutes,byte secondes){
if(heures < 10)
aff_car('0'); //affiche 0 pour les dizaines.
aff_base(heures, 10);
aff_car(':'); //insertion ':'.
if(minutes < 10)
aff_car('0'); //affiche 0 pour les dizaines.
aff_base(minutes, 10);
aff_car(':'); //insertion ':'.
if(secondes < 10)
aff_car('0'); //affiche 0 pour les dizaines.
aff_base(secondes, 10);
}
/****************************** ****************************** **************************
void tempo_ms(word temps)
****************************** ****************************** **************************/
void tempo_ms(word temps){
word j=0,i=0;
for(j = 0;j < temps ; j++) //répète temps x 1ms.
for(i = 0; i <90 ; i++); //un pas 1ms pour un quartz de 10MHz.
}
//****************************** ****************************** *************************
#endif
Ci-joint mon schéma électrique.
-----