SE3 2025/2026 EC2
Objectifs
Réaliser le programme du devoir surveillé concernant la programmation en C sur microcontrôleur AVR :
- vous disposez de la fonction
init_minuteurdu cours ; - vous devez déjà écrire une version améliorée de la fonction
shift_setdonnée en cours/TP :- la version améliorée doit s'appeller
affiche_chiffre, - cette fonction se charge de l'initialisation des registres à décalage du bouclier multifonction au premier appel,
- à chaque appel,
affiche_chiffren'affiche qu'un seul chiffre hexadécimal sur l'afficheur 7 segments, - le premier paramètre de la fonction donne la position où afficher le chiffre (les nombres valides vont de 0 à 3),
- le second paramètre donne le code ASCII du chiffre à afficher (les valeurs valides vont des caractères 0 à 9, et des caractères A à F) ;
- la version améliorée doit s'appeller
- vous écrirez ensuite un programme affichant les nombres de 0 à 9999 (en base 10), un par seconde, puis cyclant en revenant à 0 :
- il vous est imposé d'utiliser une variable globale
char nombre[4];qui contiendra les valeurs ASCII des nombres qui seront affichés sur le 7 segments, - écrivez d'abord la fonction principale
main, initialisant ce qui est nécessaire, puis affichant à tour de rôle (et à l'infini) chaque chiffre sur le 7 segments, - donnez ensuite le code de l'ISR, incrémentant les valeurs contenues dans
nombre(attention ce sont des valeurs ASCII, pour rappel les valeurs sont contiguës de 0 à 9, et de A à F).
- il vous est imposé d'utiliser une variable globale
Matériel nécessaire
- Arduino Uno avec câble USB ;
- bouclier multi-fonctions.
Documents Rendus
Objectifs
Le but de ce devoir surveillé est de réaliser un programme en langage C sur microcontrôleur AVR permettant de piloter un afficheur 7 segments à l’aide d’un registre à décalage.
Les objectifs sont les suivants :
- Utiliser la fonction init_minuteur fournie dans le cours pour configurer un timer.
- Écrire une version améliorée de la fonction shift_set appelée affiche_chiffre :
- la fonction initialise les registres à décalage lors du premier appel
- elle affiche un seul chiffre à la fois sur l’afficheur 7 segments
- le premier paramètre indique la position (de 0 à 3)
- le second paramètre correspond au code ASCII du caractère à afficher (de '0' à '9' et de 'A' à 'F')
- Mettre en place un programme affichant les nombres de 0 à 9999 :
- incrémentation chaque seconde
- retour à 0000 après 9999
- Utiliser une variable globale char nombre[4] contenant les valeurs ASCII des chiffres
- Écrire une routine d’interruption (ISR) pour gérer l’incrémentation
- Mettre en œuvre le multiplexage pour afficher les 4 chiffres
Pour cette première étape , je me suis concentré sur la communication avec le 74HC595 du Multi-function Shield. J'ai repris la base de la fonction shift_set vue en TP pour créer une fonction plus robuste nommée affiche_chiffre.
1- Principe de Fonctionnement
Le système utilise un registre à décalage pour envoyer les données à l'afficheur. Trois signaux sont utilisés :
- SER (serial)
- CLK (clock)
- LTC (Latch)
Les données ne sont pas envoyées en parallèle, mais bit pas bit (communication série).
2- Description du programme
- Le programme configue les broches utilisées comme sorties :
- PB0 pour les données (SER) - PD7 pour l'horloge (CLK) - PD4 pour la validation (LTC)
- Un tableau nommé digits contien les codes binaires nécessaires pour afficher les chiffre et les lettres sur l'afficheur 7 segments.
- La fontion affiche_chiffre permet d'afficher un caractère à une position
- si le caractère est entre '0' et '9' on utilise directement l'index correspond. - si le caractère est entre 'A' et 'F' on utilise la formule (ascii - 'A' + 10 ) - Cela permet de convertir la lettre en index dans le tableau .
- LA position de l'afficheur est sélectionnée à l'aide d'un masque binaire .
- Les données (motif +position) sont envoyées au regitre à décalage bit par bit et du bit de poinds fort au bit de poinds faible .
- une fois tous les bits envoyés , le signale LTC est activé pour afficher les données sur l'afficheur .
- Dans la fontion main une boucle infinie affiche en continu la lettre 'C' à la position 2 avec un petit délai de 5ms .
3- Code source
#include <avr/io.h>
#include <util/delay.h>
#define SFTSER_PIN PB0
#define SFTCLK_PIN PD7
#define SFTLTC_PIN PD4
static const unsigned char digits[]={
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
void affiche_chiffre(int position, char ascii){
static int initialisation = 0;
if (!initialisation){
DDRB |= (1<<SFTSER_PIN);
DDRD |= (1<<SFTCLK_PIN) | (1<<SFTLTC_PIN) ;
initialisation = 1;
}
// calcul de motif
unsigned char motif = 0xFF;
if(ascii >= '0' && ascii <= '9'){
motif = digits[ascii - '0'];
}else if (ascii >= 'A' && ascii <= 'F'){
motif = digits[ascii - 'A' + 10];
}
unsigned char pos_mask = (1<<position);
unsigned char tab[2]={motif, pos_mask};
PORTD &= ~(1<< SFTLTC_PIN); //Latch Low
for(int i= 0; i<2 ; i++){
unsigned char b = tab[i];
for (int j=7; j>=0;j--){
PORTD &= ~(1<<SFTCLK_PIN); // clock Low
if (b & (1<<j)) {
PORTB |= (1<<SFTSER_PIN);
}else{
PORTB &= ~(1<<SFTSER_PIN);
}
PORTD |=(1<<SFTCLK_PIN); // Clock High
}
}
PORTD |=(1<<SFTLTC_PIN); // Latch High
}
int main(void){
while(1){
// test / afficher sur la deuxième position
affiche_chiffre(2, 'C');
_delay_ms(5);
}
return 0;
}
4- Gestion du temps
Pour optimiser le comptage, un timer est utilisé.
- La fonction init_minuteur est fournie dans le cours.
- Le timer est configuré en mode CTC
- un diviseur est utilisé pour ajuster la vitesse
- Une interruption est générée à intervalle régulier.
Dans ce programme:
- Diviseur = 1024
- Période = 1000ms
Une Interruption toutes les 1 seconde
5- Interruption (ISR)
L’interruption TIMER1_COMPA_vect permet d’incrémenter le nombre affiché.
- Le deriner chiffre est incrémenté
- si le chiffre dépasse '9'
- il revient à '0'
- le chiffre suivant est incrémenté (retenue)
- Si 9999 est atteint :
* retour à 0000
6- Multiplexage
L'affichage des 4 chiffres est réalisé par multiplexage :
- Les chiffres sont affichés un par un très vite
- Une boucle affiche successivement chaque position :
- affiche_chiffre(i,nombre[i])
- un délai de 2ms est utilisé pour éviter le clignotement rapide
7- Code source
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define SFTSER_PIN PB0
#define SFTCLK_PIN PD7
#define SFTLTC_PIN PD4
#define CTC1 WGM12
//Variable globale
char nombre[4]={'0', '0','0','0'};
static const unsigned char digits[]={
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
void affiche_chiffre(int position, char ascii){
static int initialisation = 0;
if (!initialisation){
DDRB |= (1<<SFTSER_PIN);
DDRD |= (1<<SFTCLK_PIN) | (1<<SFTLTC_PIN) ;
initialisation = 1;
}
unsigned char motif = 0xFF;
if(ascii >= '0' && ascii <= '9'){
motif = digits[ascii - '0'];
}else if (ascii >= 'A' && ascii <= 'F'){
motif = digits[ascii - 'A' + 10];
}
unsigned char pos_mask = (1<<position);
unsigned char tab[2]={motif, pos_mask};
PORTD &= ~(1<< SFTLTC_PIN);
for(int i= 0; i<2 ; i++){
unsigned char b = tab[i];
for (int j=7; j>=0;j--){
PORTD &= ~(1<<SFTCLK_PIN);
if (b & (1<<j)) {
PORTB |= (1<<SFTSER_PIN);
}else{
PORTB &= ~(1<<SFTSER_PIN);
}
PORTD |=(1<<SFTCLK_PIN);
}
}
PORTD |=(1<<SFTLTC_PIN);
}
void init_minuteur(int diviseur,long periode){
TCCR1A=0;
TCCR1B=(1<<CTC1);
switch(diviseur){
case 8: TCCR1B |= (1<<CS11); break;
case 64: TCCR1B |= (1<<CS11 | 1<<CS10); break;
case 256: TCCR1B |= (1<<CS12); break;
case 1024: TCCR1B |= (1<<CS12 | 1<<CS10); break;
}
OCR1A=F_CPU/1000*periode/diviseur; // Calcul du pas
TCNT1=0;
TIMSK1=(1<<OCIE1A);
}
// ISR
ISR(TIMER1_COMPA_vect){
// on part du dernier chiffre
nombre[3]++;
for (int i=3; i>=0; i--){
if (nombre[i]>'9'){
nombre[i]='0';
if(i>0){
nombre[i-1]++;
}else{
// si on dépasse 9999, on revient à 0000
nombre[0]='0';
}
}
}
}
int main(void){
init_minuteur(1024,1000); //1s
sei();
while(1){
//Multiplexage: affichage des 4 digits
for (int i=0; i<4; i++){
affiche_chiffre(i,nombre[i]);
_delay_ms(2);// temps court pour éviter le clignotement
}
}
}
8- Résultats et tests
- Le compteur s’incrémente correctement chaque seconde
- Les chiffres s’affichent correctement sur les 4 positions
- Le passage de 9999 à 0000 fonctionne correctement
- L’affichage est stable grâce au multiplexage
9- Conclusion
Ce travail a permis de comprendre :
- le fonctionnement du registre à décalage 74HC595
- la communication série (bit à bit)
- l’utilisation des timers et des interruptions
- la technique du multiplexage
Le programme réalise un compteur fiable de 0000 à 9999 avec affichage dynamique.
Démonstration du système
Ressources et Documentation
- Documentation du composant 74HC595
- Cours et TP sur les registres à décalage
- Documentation AVR (ports et registres)