Cours:TPS 2103 tp1 : Différence entre versions
m (→{{Rouge|Ex 5: Drapeaux}}) |
|||
Ligne 10 : | Ligne 10 : | ||
Nous commencerons simplement de façon analogue au [[Cours:ArduinoBoutons|premier TP du module M1102]] en configurant des e/s (il est sans doute utile de jeter un coup d’œil au lien précédent !). | Nous commencerons simplement de façon analogue au [[Cours:ArduinoBoutons|premier TP du module M1102]] en configurant des e/s (il est sans doute utile de jeter un coup d’œil au lien précédent !). | ||
− | = | + | =Ex 1: mise en jambe != |
On considère [[Cours:Shieldinfo|la led f5]]. La patte correspondante (PB5) sera donc une sortie (commande) pour le µcontrôleur. On configure donc le registre de direction de la façon suivante : | On considère [[Cours:Shieldinfo|la led f5]]. La patte correspondante (PB5) sera donc une sortie (commande) pour le µcontrôleur. On configure donc le registre de direction de la façon suivante : | ||
Ligne 72 : | Ligne 72 : | ||
{{finAide}} | {{finAide}} | ||
− | |||
− | = | + | =Ex 3: bouton et led= |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Nous considérons pour le moment [[Cours:Shieldinfo|le bouton A et la led de droite (p0)]]. | Nous considérons pour le moment [[Cours:Shieldinfo|le bouton A et la led de droite (p0)]]. | ||
Ligne 160 : | Ligne 109 : | ||
*dans les autres cas, les leds sont éteintes. | *dans les autres cas, les leds sont éteintes. | ||
− | = | + | =Ex 4: Changement d'état= |
− | == | + | ==Entrées et interruptions== |
Nous allons utiliser une {{Bleu|interruption}}, dont [[Cours:Atmega328p#Interruptions|{{Rouge|vous devez comprendre le fonctionnement en lisant ce lien !}}]] | Nous allons utiliser une {{Bleu|interruption}}, dont [[Cours:Atmega328p#Interruptions|{{Rouge|vous devez comprendre le fonctionnement en lisant ce lien !}}]] |
Version du 3 février 2022 à 12:13
Nous avons abordé la programmation des cartes arduino au premier semestre en utilisant des fonctions de haut niveau ce qui, bien que pouvant simplifier certaine tâche, présente un certain nombre de limitation.
L'objectif de ces TPs est de découvrir le fonctionnement du µcontrôleur Atmega328p et d'en explorer les possibilités.
Nous commencerons simplement de façon analogue au premier TP du module M1102 en configurant des e/s (il est sans doute utile de jeter un coup d’œil au lien précédent !).
Sommaire
Ex 1: mise en jambe !
On considère la led f5. La patte correspondante (PB5) sera donc une sortie (commande) pour le µcontrôleur. On configure donc le registre de direction de la façon suivante :
DDRB bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Valeur | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
On rappelle la connexion des LEDs et couleur avec les PORTs correspondants pour le shield de l'IUT de Troyes :
Numéro | f5 | f4 | f3 | f2 | f1 | f0 | p1 | p0 |
---|---|---|---|---|---|---|---|---|
Couleur | r | o | v | r | o | v | v | r |
Arduino Pin | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 |
Port Arduino UNO | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | PD7 | PD6 |
Port Arduino LEONARDO | PC7 | PD6 | PB7 | PB6 | PB5 | PB4 | PE6 | PD7 |
Compléter le programme suivant pour que la led s'allume et s'éteigne pendant 500ms
Remarque : On utilisera astucieusement l'opérateur ^
#include <avr/io.h>
#include <util/delay.h>
int main()
{
DDRB |= ... ; // configuration des e/s (registre de direction DDRx) sur le port D.
while(1)
{
PORTB ???? ; // on modifie en conséquence l'état de la sortie
.... // il faudra utiliser la fonction _delay_ms() !
}
}
#include <avr/io.h>
#include <util/delay.h>
int main()
{ // setup()
DDRB |= 1<<PB0 ; // configuration des e/s (registre de direction DDRx) sur le port D.
// loop()
while(1) {
PORTB &=~ (1<<PB0) ; // mise à zéro de la sortie
_delay_ms(500);
PORTB |= 1<<PB0 ; // mise à un de la sortie
_delay_ms(500);
}
return 0;
}
Notez encore la présence de deux parties différentes dans ce programme :
|
Ex 3: bouton et led
Nous considérons pour le moment le bouton A et la led de droite (p0).
Le tableau suivant donne les caractéristiques utiles sur les 4 boutons poussoirs d'entrée pour le shield de l'IUT :
Bouton | Position | Arduino Pin | Port | Interruption | Niveau logique si bouton appuyé |
---|---|---|---|---|---|
A | Bas Gauche | 2 | PD2 | int0 | 1 |
D | Haut Gauche | 3 | PD3 | int1 | 1 |
B | Bas Droite | A0 | PC0 | 0 | |
C | Haut Droite | A1 | PC1 | 0 |
Complétez le programme suivant pour que la led s'allume si le bouton est appuyé
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sfr_defs.h>
int main()
{
DDRD |= .... ; // configuration des e/s (registre de direction DDRx) sur le port D.
while(1)
{
if ( bit_is_set(PIND,???? ) ) // on observe l'état de l'entrée
PORTD ..... ; // on modifie en conséquence l'état de la sortie
else
PORTD ..... ;
}
}
Il vous reste moins d'1h pour terminer le TP, passez à la partie suivante !
On ajoute un 2ème bouton (bp B) et une 2ème led (led p1) et modifier le programme pour que :
- si le bp B est appuyé, la led p0 s'allume
- la led p1 ne s'allume que si les 2 boutons sont appuyés
- dans les autres cas, les leds sont éteintes.
Ex 4: Changement d'état
Entrées et interruptions
Nous allons utiliser une interruption, dont vous devez comprendre le fonctionnement en lisant ce lien !
Commencer par comprendre et exécuter le code donné en exemple
Modifier le programme pour que la led(p0) ne change d'état qu'à l'appui sur le bouton poussoir, et non à chaque changement d'état
|
Et pour 2 leds ??
Adapter le programme précédent en ajoutant le bouton D (INT1) et une led au choix avec un fonctionnement identique (chaque bouton commande 1 led)
Autre possibilité
Bien évidemment 2 interruptions peuvent modifier la même variable/registre :
On souhaite que l'appui sur le bouton A allume la led p0 et l'appui sur le bouton D l'éteigne. Écrire le programme.
Ex 5: Drapeaux
Les drapeaux sont très utilisés avec les fonctions d'interruption. Le principe est de positionner une variable à une valeur particulière au sein de l'interruption et de faire un test sur cette valeur dans le programme principal, exemple :
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned char chg = 0; // les variables partagées entre interruption et programme principale doivent être de type volatile
ISR(INT0_vect) // programme d'interruption : le programme principal est interrompu,
{ // l'interruption exécutée et ensuite le programme principal continue normalement son exécution
chg = 1; // on positionne le drapeau/flag
}
int main()
{
DDRB |= (1<<PB0); // configuration de PB0 en sortie
cli(); // arrêt des interruptions
EICRA |= (1<<ISC00); // mode de déclenchement de l'interruption
EIMSK |= (1<<INT0); // choix des interruptions actives
sei(); // autorisation des interruptions
while(1)
{
if (chg == 1)
{
PORTB ^= (1<<PB0);
chg=0;
}
}
}
Premier usage
Modifier le programme précédent pour :
- Ne déclencher l'interruption que sur un appui du bouton A
- Incrémenter le drapeau à chaque interruption
- Changer l'état de la led tous les 5 appuis
Clignotement
Écrire le programme répondant au cahier des charges suivant :
- Faire clignoter une led
- Chaque appui sur A double la fréquence de clignotement
- Chaque appui sur D divise par 2 la fréquence de clignotement
Attention, il faut ajouter obligatoirement __DELAY_BACKWARD_COMPATIBLE__ :
#include <avr/io.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <avr/interrupt.h>
Complément : Changement d'état sans interruptions
Explication
Malheureusement, toutes les entrées ne peuvent déclencher une interruption spécifique.
Dès lors, il peut être utile de changer de technique pour détecter les changements d'état des entrées.
C'est ce que nous proposons d'étudier dans cette parties.
Passé Présent
On souhaite maintenant changer l'état de la led (p0) à chaque appui sur le bouton poussoir A (PD2).
On rappelle comme vu en module M1103 que l'une des méthodes repose sur la notion de présent et passé.
Le code suivant (à compléter) répond à ce cahier des charges
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sfr_defs.h>
uint8_t etatPresent=0,etatPasse=0;
unsigned char etatSortie=0;
int main()
{
DDRD |= (1<<...); // configuration des e/s
while(1)
{
etatPasse=etatPresent;
if ( bit_is_clear(PINx,....) ) // si le bouton est relâché
etatPresent = 0;
else etatPresent = 1;
if ((etatPresent != 0) && (etatPasse == 0)) PORTD ^= (1<<...); // modifier la sortie associée à la led p0
}
}
#include <avr/sfr_defs.h>
uint8_t etatPresent=0,etatPasse=0;
unsigned char etatSortie=0;
int main()
{
DDRD |= (1<<...); // configuration des e/s
while(1)
{
etatPasse=etatPresent;
etatPresent = bit_is_set(PIND,.... ); // 2 valeurs possibles pour etatPresent : 0 ou "différent de 0"
if ((etatPresent != 0) && (etatPasse == 0)) PORTD ^= (1<<..); // modifier la sortie associée à la led p0
}
}
|
Utilisation
En utilisant ce principe, écrire le programme répondant à la question suivante :
La led (à choisir) s'allume à l'appui sur le bouton B, et s'éteint à l'appui sur C