Bienvenue aux nouveaux arrivants sur FantasPic !
- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
Afficheur 7 segments (Digits)
-
Jérémy
Administrateur du site- Messages : 2725
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Bonjour à tous,
Je vous propose un tutoriel sur le fonctionnement des afficheurs 7 segments "Digit" avec MikroC.
Les pré-requis :
Configuration :
- PIC18F46K22
- IDE : MikroC Pro for PIC Version 6.6.3
- Compilateur : Mikro prog suite fo PIC V 2.32
- Plaque Easy PIC V7
Un afficheur 7 segments appelé également "digit" est un composant permettant l'affichage de chiffres et de lettres en combinant et en allumant ces différents segments.
Chaque segment ( qui sont des leds) doit être connecté à une broche de notre PIC. Suivant l'afficheur 7 segments utilisé, anode ou cathode commune il faudra un "état haut" ou un "état bas" pour allumer celui-ci.
Le Schéma :
Voici le schéma de la partie "DIGIT" de la carte EasyPic7. Chaque segments des digits est relié au PORTD de 0 à 7 . "0" correspondant au segment "a" et 7 à "dp" pour "décimal point".
Les transistors sont reliés au PORT A ( de RA0 à RA3) et active ou non les digits correspondants, le premier Digit(à droite) est branché sur RA0.
Nous allons voir comment se servir d'un seul digit pour commencer !!!
Le but :
Nous allons créer un compteur, comptant de 0 à 9. Il devra afficher sa valeur sur un DIGIT( RA0). Aucune précision n'est souhaité et une pause servira de temporisation.
Une fonction permettra de convertir le chiffre de notre compteur, en une valeur définissant les segments à allumés.
par exemple pour affichés "1" : il faudra affiché les deux segments verticaux à droite .
ces deux segments correspondent aux segments "b" et "c". Ce qui fais 0b00000110 = 0x06
Programme pour un seul "digit" :
Remarques :
Le problème avec les digits c'est qu'ils sont gourmands en connexions, 8 en général, 7 pour les segments et 1 pour le point. Donc si on veut afficher des nombres avec plus de un chiffre, ça devient assez problématique. Pour éviter de monopoliser autant de broches , on va utiliser le multiplexage .
le multiplexage consiste à allumer successivement les afficheurs les uns après les autres, très rapidement . On ne verra pas de clignotement grâce a la persistance rétinienne.
Le déroulement se fera ainsi :
Programme pour 4 afficheurs 7 segments :
Voici le programme, non optimisé, pour bien vous faire comprendre le principe. Ici un afficheur sera actif toutes 15ms pendant 5 ms. On ne voit aucun clignotement !.
Bien évidemment suivant votre programme principal, d'autres solutions plus optimisées sont largement conseillées. Ici on ne fait que compter et afficher, c'est rarement le cas dans les projets !
Notez la fonction modulo, qui nous sert à extraire les chiffres correspondant aux différentes unités .
Conseils :
- Conseil de Paulfjujo : Sur les PIC 18F, l'affection d'une valeur sur un PORT se fait avec le mot LATx plutôt que PORTx.
- Ici nous utilisons des delay_ms, pour temporiser l'affichage, sinon cela y aurai bien trop vite pour nos yeux et on verrait tous les segments s'allumés en même temps. N'oubliez pas que pendant un delay_ms, votre µC ne peut rien faire.
La bonne méthode serait de passer par un timer afin de libérer notre µC pendant ces pauses. voici un exemple de ce qui pourrait être fait
Vidéo :
http://www.dailymotion.com/video/x37y6p2
Comme d'habitude, pour les experts si vous voyez des erreurs ou avez des astuces , vous pouvez poster à la suite, je mettrais le Tuto à jour .
Pour les moins Experts qui veulent approfondir ou poser des questions , n’hésitez surtout pas et postez aussi à la suite!.
Je vous propose un tutoriel sur le fonctionnement des afficheurs 7 segments "Digit" avec MikroC.
Les pré-requis :
- Le Modulo : %.
- La fonction : switch.
- Fonction avec paramètres d'entrée et de sortie.
Configuration :
- PIC18F46K22
- IDE : MikroC Pro for PIC Version 6.6.3
- Compilateur : Mikro prog suite fo PIC V 2.32
- Plaque Easy PIC V7
Un afficheur 7 segments appelé également "digit" est un composant permettant l'affichage de chiffres et de lettres en combinant et en allumant ces différents segments.
Chaque segment ( qui sont des leds) doit être connecté à une broche de notre PIC. Suivant l'afficheur 7 segments utilisé, anode ou cathode commune il faudra un "état haut" ou un "état bas" pour allumer celui-ci.
Le Schéma :
Voici le schéma de la partie "DIGIT" de la carte EasyPic7. Chaque segments des digits est relié au PORTD de 0 à 7 . "0" correspondant au segment "a" et 7 à "dp" pour "décimal point".
Les transistors sont reliés au PORT A ( de RA0 à RA3) et active ou non les digits correspondants, le premier Digit(à droite) est branché sur RA0.
Nous allons voir comment se servir d'un seul digit pour commencer !!!
Le but :
Nous allons créer un compteur, comptant de 0 à 9. Il devra afficher sa valeur sur un DIGIT( RA0). Aucune précision n'est souhaité et une pause servira de temporisation.
Une fonction permettra de convertir le chiffre de notre compteur, en une valeur définissant les segments à allumés.
par exemple pour affichés "1" : il faudra affiché les deux segments verticaux à droite .
ces deux segments correspondent aux segments "b" et "c". Ce qui fais 0b00000110 = 0x06
Programme pour un seul "digit" :
Code : Tout sélectionner
/*##################################################################################
############################## Variable / Constante #########################
##################################################################################*/
unsigned int compteur, num ; // Déclaration des variables
/*##################################################################################
########################### CONVERTIR LE CHIFFRE #############################
##################################################################################*/
unsigned short conversion(unsigned short num) // Fonction avec paramètres d'entrée et de sortie
{ // suivant le chiffre du compteur on renvoie la valeur pour allumer tel ou tel segments sur le PORTD
// Utilisation de la commande "switch"
switch (num) { // "Switch" compare la valeur contenu dans "num" aux valeurs "case" ci dessous
// Si une valeur est trouvée, "Switch" renvoie la valeur correspondante et sort
// Une seule valeur est prise en compte
case 0 : return 0x3F; // Affiche un "0" avec l'allumage de six segments 3F = 00111111 du PORTD
case 1 : return 0x06; // |
case 2 : return 0x5B; // |
case 3 : return 0x4F; // |
case 4 : return 0x66; // |
case 5 : return 0x6D; // |
case 6 : return 0x7D; // |
case 7 : return 0x07; // |
case 8 : return 0x7F; // |
case 9 : return 0x6F; // Affiche un "9" par l'allumage des segments correspondants
}
}
/*##################################################################################
############################ PROGRAMME PRINCIPAL ##############################
##################################################################################*/
void main() {
ANSELA = 0; // Configure le PORTA en Digital
ANSELD = 0; // Configure le PORTD en Digital
TRISA = 0; // Configure le PORTA en SORTIE
LATA = 0; // affecte 0 aux broches du PORTA
TRISD = 0; // Configure le PORTD en SORTIE
LATD = 0; // affecte 0 aux broches du PORTD
LATA.B0 = 1; // Mise à l'état haut de RA0 pour activer le premier afficheur.
compteur = 0; // Initialise notre compteur à 0.
//########################## BOUCLE INFINIE ##################################
do {
if (compteur >= 10) compteur = 0 ; // Si le compteur est supérieur ou égale a 10 alors on le remet à 0
LATD = conversion(compteur) ; // on affecte la valeur convertie pour affichage sur le PORT D
compteur = compteur++; // On incrémente notre compteur.
delay_ms(1000); // On marque une pause de 1 seconde.
} while(1); // On reboucle
}
Remarques :
Le problème avec les digits c'est qu'ils sont gourmands en connexions, 8 en général, 7 pour les segments et 1 pour le point. Donc si on veut afficher des nombres avec plus de un chiffre, ça devient assez problématique. Pour éviter de monopoliser autant de broches , on va utiliser le multiplexage .
le multiplexage consiste à allumer successivement les afficheurs les uns après les autres, très rapidement . On ne verra pas de clignotement grâce a la persistance rétinienne.
Le déroulement se fera ainsi :
- activation du premier digit -> Affichage d'un chiffre -> désactivation du premier digit
- activation du deuxième digit -> Affichage d'un chiffre -> désactivation du deuxième digit
- activation du troisième digit -> Affichage d'un chiffre -> désactivation du troisième digit
- activation du quatrième digit -> Affichage d'un chiffre -> désactivation du quatrième digit
- et on reboucle.
Programme pour 4 afficheurs 7 segments :
Voici le programme, non optimisé, pour bien vous faire comprendre le principe. Ici un afficheur sera actif toutes 15ms pendant 5 ms. On ne voit aucun clignotement !.
Bien évidemment suivant votre programme principal, d'autres solutions plus optimisées sont largement conseillées. Ici on ne fait que compter et afficher, c'est rarement le cas dans les projets !
Notez la fonction modulo, qui nous sert à extraire les chiffres correspondant aux différentes unités .
Code : Tout sélectionner
/*##################################################################################
############################## Variable / Constante #########################
##################################################################################*/
unsigned int compteur, num,millier, centaine, dizaine, unite; // Déclaration des variables
/*##################################################################################
########################### CONVERTIR LE CHIFFRE #############################
##################################################################################*/
unsigned short conversion(unsigned short num) // Fonction avec parametres d'entrée et de sortie
{ // suivant le chiffre du compteur on renvoie la valeur pour allumer tel ou tel segments sur le PORTD
// Utilisation de la commande "switch"
switch (num) { // "Switch" compare la valeur contenu dans "num" au valeur "case" ci dessous
// Si une valeur est trouvée, "Switch" renvoie la valeur toucorrespondante et sort
// Une seule valeur est prise en compte
case 0 : return 0x3F; // Affiche un "0" avec l'allumage de six segments 3F = 00111111 du PORTD
case 1 : return 0x06; // |
case 2 : return 0x5B; // |
case 3 : return 0x4F; // |
case 4 : return 0x66; // |
case 5 : return 0x6D; // |
case 6 : return 0x7D; // |
case 7 : return 0x07; // |
case 8 : return 0x7F; // |
case 9 : return 0x6F; // Affiche un "9" par l'allumage des segments correspondants
}
}
/*##################################################################################
############################ PROGRAMME PRINCIPAL ##############################
##################################################################################*/
void main() {
ANSELA = 0; // Configure le PORTA en Digital
ANSELD = 0; // Configure le PORTD en Digital
TRISA = 0; // Configure le PORTA en SORTIE
LATA = 0; // affecte 0 aux broches du PORTA
TRISD = 0; // Configure le PORTD en SORTIE
LATD = 0; // affecte 0 aux broches du PORTD
compteur = 0; // Initialise notre compteur à 0.
//########################## BOUCLE INFINIE ##################################
do {
millier = compteur/1000 %10 ; // Calcul de la valeur des milliers . On divise le compteur par 1000 on prend le modulo
LATD = conversion(millier); // On convertit la valeur calculée en segments pour affichage.
LATA = 8; // On active le 4iéme digit ( 0b00001000) en mettant le bit 3 à 1
delay_ms (5); // On marque une pause pour afficher le chiffre
centaine = compteur/100 %10; // calcul de la valeur des centaines . On divise le compteur par 100 on prend le modulo
LATD = conversion(centaine); // On convertit la valeur calculée en segments pour affichage.
LATA = 4; // On active le 3iéme digit ( 0b00000100) en mettant le bit 2 à 1
delay_ms (5); // On marque une pause pour afficher le chiffre
dizaine = compteur/10 %10; // calcul de la valeur des dizaines . On divise le compteur par 10 on prend le modulo
LATD = conversion(dizaine); // On convertit la valeur calculée en segments pour affichage.
LATA = 2; // On active le 2iéme digit ( 0b00000010) en mettant le bit 1 à 1
delay_ms (5); // On marque une pause pour afficher le chiffre
unite = compteur %10; // calcul de la valeur des unités . On prend le modulo
LATD = conversion(unite); // On convertit la valeur calculée en segments pour affichage.
LATA = 1; // On active le 1er digit ( 0b00000001) en mettant le bit 0 à 1
delay_ms (5) ; // On marque une pause pour afficher le chiffre
compteur = compteur++ ; // On incrémente notre compteur
} while(1); // On reboucle
}
Conseils :
- Conseil de Paulfjujo : Sur les PIC 18F, l'affection d'une valeur sur un PORT se fait avec le mot LATx plutôt que PORTx.
- Ici nous utilisons des delay_ms, pour temporiser l'affichage, sinon cela y aurai bien trop vite pour nos yeux et on verrait tous les segments s'allumés en même temps. N'oubliez pas que pendant un delay_ms, votre µC ne peut rien faire.
La bonne méthode serait de passer par un timer afin de libérer notre µC pendant ces pauses. voici un exemple de ce qui pourrait être fait
► Afficher le programme
Vidéo :
http://www.dailymotion.com/video/x37y6p2
Comme d'habitude, pour les experts si vous voyez des erreurs ou avez des astuces , vous pouvez poster à la suite, je mettrais le Tuto à jour .
Pour les moins Experts qui veulent approfondir ou poser des questions , n’hésitez surtout pas et postez aussi à la suite!.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Afficheur 7 segments (Digits)
Afficheur 7 segments (Digits)
Afficheur 7 segments (Digits)
Afficheur 7 segments (Digits)
A pic !
Merci beaucoup Jérémy pour ce tuto très propre.
@++
Merci beaucoup Jérémy pour ce tuto très propre.
@++
Afficheur 7 segments (Digits)
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
bonjour,
Belle presentation ..
juste un petit detail..
dans ton init tu utilises bien LATD=0
par contre dans le programme, il faudrait, pour garder une bonne habitude avec les 18F ,
remplacer les affectations comme
PORTD = conversion(compteur) ;
par
LATD= conversion(compteur) ;
meme si cela fonctionne dans ce cas là.
Belle presentation ..
juste un petit detail..
dans ton init tu utilises bien LATD=0
par contre dans le programme, il faudrait, pour garder une bonne habitude avec les 18F ,
remplacer les affectations comme
PORTD = conversion(compteur) ;
par
LATD= conversion(compteur) ;
meme si cela fonctionne dans ce cas là.
Afficheur 7 segments (Digits)
Afficheur 7 segments (Digits)
salut Jérémy
pour quoi tu n'utilise pas un tableau au lieu la fonction de conversion
exemple
par
pour quoi tu n'utilise pas un tableau au lieu la fonction de conversion
exemple
unsigned short conversion(unsigned short num) // Fonction avec paramètres d'entrée et de sortie
{ // suivant le chiffre du compteur on renvoie la valeur pour allumer tel ou tel segments sur le PORTD
// Utilisation de la commande "switch"
switch (num) { // "Switch" compare la valeur contenu dans "num" aux valeurs "case" ci dessous
// Si une valeur est trouvée, "Switch" renvoie la valeur correspondante et sort
// Une seule valeur est prise en compte
case 0 : return 0x3F; // Affiche un "0" avec l'allumage de six segments 3F = 00111111 du PORTD
case 1 : return 0x06; // |
case 2 : return 0x5B; // |
case 3 : return 0x4F; // |
case 4 : return 0x66; // |
case 5 : return 0x6D; // |
case 6 : return 0x7D; // |
case 7 : return 0x07; // |
case 8 : return 0x7F; // |
case 9 : return 0x6F; // Affiche un "9" par l'allumage des segments correspondants
}
}
par
const unsigned char conversion[] = {0x3f,0x06,0x5b......}
et
LATD = conversion(compteur) ; // on affecte la valeur convertie pour affichage sur le PORT D
par
LATD = conversion[compteur] ; // on affecte la valeur convertie pour affichage sur le PORT D
Afficheur 7 segments (Digits)
-
Jérémy
Administrateur du site- Messages : 2725
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Bonjour Omar,
Merci de l’intérêt porté à ce Tuto c'est une très bonne suggestion ! c'est une autre façon de faire qui mérite d'être vue. Je vais voir pour mettre à jour le tuto !
D’après toi quelle serait les avantages d'utiliser un tableau plutôt qu'une fonction ? afin d'argumenter mon tuto ?
Bonne journée
Merci de l’intérêt porté à ce Tuto c'est une très bonne suggestion ! c'est une autre façon de faire qui mérite d'être vue. Je vais voir pour mettre à jour le tuto !
D’après toi quelle serait les avantages d'utiliser un tableau plutôt qu'une fonction ? afin d'argumenter mon tuto ?
Bonne journée
Afficheur 7 segments (Digits)
- Claudius
Passionné- Messages : 260
- Âge : 69
- Enregistré en : septembre 2015
- Localisation : ELANCOURT (78 - YVELINES)
- Contact :
Bonsoir et Bonne Année à tous,
L'utilisation d'un tableau est une excellente idée car l'accès à la valeur est pratiquement en temps constant alors qu'avec un switch / case, les données sont accédées en un temps fonction de sa place dans le case (du moins si le compilateur ne les réorganise pas). En effet un switch / case est transcrit par les compilateurs (sauf exception et à vérifier par désassemblage du code généré) par une suite de if/ else if / ... / else if / else
Maintenant, une autre astuce est d'écrire en assembleur ledit tableau comme suit pour un pic16 (je n'ai pas vérifié avec un pic18):
Avec cette dernière implémentation, le temps d'accès est constant quelle que soit la place de la valeur à retourner (attention à la taille de cette subroutine qui doit être définie un et un seul bank. et ne pas chevaucher 2 bank différents)...
Cf. pour tout savoir: Implementing a Table Read ;-)
L'utilisation d'un tableau est une excellente idée car l'accès à la valeur est pratiquement en temps constant alors qu'avec un switch / case, les données sont accédées en un temps fonction de sa place dans le case (du moins si le compilateur ne les réorganise pas). En effet un switch / case est transcrit par les compilateurs (sauf exception et à vérifier par désassemblage du code généré) par une suite de if/ else if / ... / else if / else
Maintenant, une autre astuce est d'écrire en assembleur ledit tableau comme suit pour un pic16 (je n'ai pas vérifié avec un pic18):
Code : Tout sélectionner
conversion
addwf PCL,F
retlw 0x3F ; Retourne un "0" avec l'allumage de six segments 3F = 00111111 du PORTD
retlw 0x06 ; |
retlw 0x5B ; |
retlw 0x4F ; |
retlw 0x66 ; |
retlw 0x6D ; |
retlw 0x7D ; |
retlw 0x07 ; |
retlw 0x7F ; |
retlw 0x6F ; Retourne un "9" avec l'allumage des segments correspondants
Avec cette dernière implémentation, le temps d'accès est constant quelle que soit la place de la valeur à retourner (attention à la taille de cette subroutine qui doit être définie un et un seul bank. et ne pas chevaucher 2 bank différents)...
Cf. pour tout savoir: Implementing a Table Read ;-)
Enregistreur de traces GPS & Boussole GPS parlante (PIC & Arduino)
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 31 invités