[go: up one dir, main page]
More Web Proxy on the site http://driver.im/

TP Atmega

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 8

Travaux Pratiques

2024 – 2025

Master Big Data et Internet des Objets

Atmega32u4 – Langage C

Session d’Automne
Enseignant: BABA
youssef.baba@univh2c.ma
Objectifs :
¨ Exploiter une chaîne de développement : avr-gcc (compilateur), teensy_loader et avrdude
¨ Mettre en œuvre la gestion des entrées-sorties du microcontrôleur atmega32u4.
¨ Écrire un programme en langage C pour microcontrôleur (structure de base : variables, boucles, tests).

Matériel :
TP1 – TP2
¨ Carte Teensy 2.0 (i/o: 5V – quartz: 16MHz).
¨ Boutons poussoirs utilisateurs : 02 (PB1 ; PB2)
¨ LEDs : 03 (PD4 ; PD5 ; PD6)
¨ Sur la planche de test, les pins PB2 et PD0 sont connectés par un fil sous la carte Teensy

TP3– TP4 (document séparé)


¨ Carte Adafruit Circuit Playground Classic (i/o: 3V3 – quartz: 8MHz).
¨ Boutons poussoirs utilisateurs : 02 (PF6 ; PD4)
¨ LED : 01 (PC7)
¨ Capteur de lumière (PF0)
¨ Capteur de température (PF7)

Table des matières :

TP 0 – Setup et Installations
i. Avr-gcc
ii. Programmeur
iii. Atmel Studio
iv. Arduino Ide

TP 1 – PORTS d'E/S et Temporisation


Application 1 : chenillard
Application 2 : bouton poussoir
Application 3 : Interruption externe INT0
Application 4 : TIMER Interruptions

TP 2 – USART
Application 5 : UART
Application 6 : Interruptions UART
TP 0 – Setup et Installations

i. Avr-gcc

L’outil libre avr-gcc est nécessaire pour compiler un code C écrit pour la famille des microcontrôleurs AVR
de MICROCHIP. Avr-gcc permet de créer un fichier hex qui sera téléversé dans la carte microcontrôleur
pour la programmer l’atmega32u4.

Pour installer avr-gcc consulter ces liens:


https://winavr.sourceforge.net/
https://www.pololu.com/docs/0J61/6.3

ii. Chargeur de Programme

On aura besoin d’installer un programmeur :

1. Teensy loader pour la carte Teensy

Visiter la page : https://www.pjrc.com/teensy/loader.html pour l’installer. Il est disponible en mode


graphique, mais aussi en mode ligne de commande (créer l’exécutable soi-même à partir des fichiers
sources). Ce dernier est préférable si on souhaite travailler avec un Makefile pour automatiser le processus
d’exécution.

2. AVRDUDE pour la carte Adafruit

Visiter la page : https://github.com/avrdudes/avrdude. Il est disponible en mode ligne de commande


seulement.
Pour tester les outils installés, créer un fichier main.c et un fichier Makefile :
main.c makefile
#define F_CPU 16000000UL MCU=atmega32u4
#include <avr/io.h> FLAG=-Os -Wall
#include <util/delay.h> all:
int main(void) { avr-gcc -mmcu=$(MCU) $(FLAG) -c main.c
DDRD=0xF0; avr-gcc -mmcu=$(MCU) $(FLAG) -o main.out main.o
while (1) { avr-objcopy -R .eeprom -O ihex main.out main.hex
PIND |=1<<6;
_delay_ms(200); burn:
} return 0;} teensy --mcu=$(MCU) -w main.hex

Ouvrir un terminal et exécuter la commande :


make && make burn

Appuyer sur le bouton Boot pour laisser le bootloader charger le fichier binaire et exécuter le code.

Master – Département GE – BABA 3 modifié le 29 Oct. 2024


TP 0 – Setup et Installations

iii. Atmel Studio 7

Atmel Studio permet de développer facilement votre projet C/C++ (plusieurs étudiants préfèrent cette
solution). Atmel Studio intègre le compilateur Avr-gcc et il peut être configuré pour programmer également
la carte à microcontrôleur. C’est un bon choix puisqu’il permet de déboguer le code C/C++ en offrant la
possibilité de voir les valeurs des différents registres de l’Atmega32u4 durant l’exécution du programme.

Télécharger et installer Atmel Studio 7 en se référant au lien suivant :


https://ww1.microchip.com/downloads/aemDocuments/documents/DEV/ProductDocuments/SoftwareToo
ls/as-installer-7.0.2542-full.exe

Cocher la première option pour utiliser les microcontrôleurs AVR 8-bits et ignorer par exemple d’installer
les prérequis pour les microcontrôleurs SAM (ARM). Une fois installé, chercher si une mise à jour est
disponible. Suivre ce tuto pour commencer à utiliser le logiciel : https://www.pololu.com/docs/0J36/3.b

iv. Arduino Ide

Télécharger et installer la dernière version d’Arduino IDE :


https://www.arduino.cc/en/Main/Software

Install Drivers (Windows 7 Only) :


https://learn.adafruit.com/introducing-circuit-playground/windows-driver-installation

Installer Teensyduino (une extension Arduino) pour utiliser la carte Teensy avec Arduino Ide :
https://www.pjrc.com/teensy/td_download.html

Le logiciel Arduino utilise un langage dédié qui se base sur le langage C++ dit simplement Arduino. Ce
langage est basé sur deux fonctions principales :

void setup() {
// put your setup code here, to run once:
}

void loop() {
// put your main code here, to run repeatedly:
}

Cette approche cache une utilisation non souhaitée des ressources du microcontrôleur : à cause de la
méthode de compilation implémentée par Arduino. On peut donc utiliser le logiciel (avec prudence) en
supprimant les deux fonctions par défaut, et en utilisant une fonction int main() {} standard. Noter que la
fonction doit absolument retourner un type int. Un autre intérêt de l’utilisation du logiciel Arduino est la
possibilité de téléverser le fichier hex de façon automatique en utilisant l’outil teensy_loader :
https://www.pjrc.com/teensy/loader.html

Master – Département GE – BABA 4 modifié le 29 Oct. 2024


Application 1 : chenillard

Créer le dossier app_1 puis y ajouter le fichier source chenillard.c dont le code est donné ci-dessous.
#include <io.h>
#include <delay.h>

int main() {
CLKPR = 0x80; CLKPR = 0x00;//required for this board version
while(1) {
PORTD ^=(7<<4); //toogle D6-D5-D4
DELAY_ms(500);//delay 0.5s
}
return 0;
}

Q1.1 : compiler le programme. Programmer. Tester. Le chenillard fonctionne-t-il ?


Q1.2 : modifier le programme pour qu’il produise un chenillard qui fonctionne
Q1.3 : modifier le programme pour que le chenillard réalise un aller/retour.

Application 2 : bouton poussoir


Créer un nouveau répertoire app_2. Écrire un programme bouton.c et y ajouter le code suivant qui permet
à la carte Teensy d’échanger des données avec le PC en utilisant un port serié.

#include "usb.h"
#include <stdbool.h>
int main(void) {
CLKPR = 0x80; CLKPR = (0);
char value;
usb_init();
while(!usb_isconnected()); // wait for a connection
while(1) {
if(usb_rx_available())
{ value = usb_rx_char();
usb_tx_char(value);
if(usb_rx_available()==0) usb_tx_char('\n'); }
} return 0;
}
Remarque : le code ci-dessus ne fonctionne pas dans Arduino. Car Arduino implémente sa propre classe
usb-cdc notée Serial, et qui utilise les mêmes routines d’interruptions dans usb.c
Q2.1 : Proposer un code qui permettra d’inverser l’état de la led jaune à chaque appui sur le bouton PB1.
Q2.2 : Que constatez-vous ?
Q2.3 : Modifier le code pour afficher (sur un moniteur série dans votre PC) l’état de la led et le nombre
de fois d’appui sur le bouton poussoir.

Application 3 : Interruption externe INT0


Les pistes PB2 et PD0 sont connectés par un fil sous la carte Teensy. Il est donc possible d’utiliser le bouton
poussoir BP2 pour générer une interruption externe INT0. Vérifier-le avant de commencer le TP.
Créer le fichier app_3/main.c et y insérer le code ci-dessous.

Master – Département GE – BABA 5 modifié le 29 Oct. 2024


#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h> // _delay_ms

// software debounce
ISR(INT0_vect) {PORTB ^= 1<<PD6; _delay_ms(100);}

int main(void)
{ CLKPR = 0x80; CLKPR = 0x00;//required for this Teensy
MCUCR &=~(1<<PUD);//
DDRD &= ~(1<<PD0) ; //PD0 input (int0)
DDRD |= (1<<PD6) ; //PD6 output (LED_D6)
PORTD |= (1<<PD0) ; //enable pullup on PD0
DDRB |=(1<<PB0) ; //PB0 output (LED_B0)
EIMSK = 1<<INT0 ; //enable int0
sei();
while(1) {PORTB^=1<<PORTB0;_delay_ms(200);}
}//fin main

Q3.1 : Que constatez-vous si vous maintenez enfoncé le bouton sur PD0? Pourquoi ?
Q3.2 : Proposer une solution déclenchant un drapeau dans l’ISR et gérant les conséquences de ce drapeau
(changement d’état de la LED_PD6) dans la fonction principale (main()). On pourra réactiver les
interruptions (sei()) une fois le drapeau traité dans le programme principal.
Q3.3 : Modifier le code pour déclencher l’interruption sur un front descendant.

Application 4 : TIMER Interruptions


Le Timer0 codé sur 8 bits va de 0 à 255, le Timer1 codé sur 16 bits de 0 à 65535 .

TCCR0B: TCCR0B: TCCR0B: Prescaler TCCR1B: TCCR1B: TCCR1B: Prescaler


CS02 CS01 CS00 CS12 CS11 CS10

0 0 0 inactif 0 0 0 inactif

0 0 1 /1 0 0 1 /1

0 1 0 /8 0 1 0 /8
0 1 1 /64 0 1 1 /64
1 0 0 /256 1 0 0 /256

1 0 1 /1024 1 0 1 /1024
Configuration de l’horloge du Timer0 Configuration de l’horloge du Timer1
Soit le code source app_4/main.c
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
volatile char c = 0;

ISR (TIMER1_OVF_vect) {PORTD ^= (1<<PD5);}


ISR (TIMER0_OVF_vect) {c++; if(c==5) {PORTD ^= (1<<PB4);c=0;}}

Master – Département GE – BABA 6 modifié le 29 Oct. 2024


int main() {
CLKPR = 0x80; CLKPR = 0x00;//required for this teensy
MCUCR &=~(1<<PUD);//
DDRD |= (1 << PD5) | (1<<PD4);
TCCR0B = (1<<CS00) | (1<<CS02); //Prescaler = 1024
TCCR1B = (1<<CS10) | (1<<CS11); //Prescaler = 64
TIMSK0 = (1<<TOIE0);
TIMSK1 = (1 << TOIE1); //enable Overflow interrupt
sei();
while(1);}

Q4.1 : Sachant que F_CPU=16000000, quelle est la fréquence de clignotement de LED5 et LED4 ?
Q4.2 : Quelle condition sur c faudrait-il ajouter pour que la diode commute à 0.5 Hz ?
Q4.3 : Modifier le programme du fichier app_4/main.c, pour que les deux Timer fonctionnent en mode
CTC. La boucle (while(1)) de la fonction main() doit être vide. L’évolution du motif des LEDs est donnée
exclusivement dans le gestionnaire d’interruption ISR.

Application 5 : UART

Brancher la broche TX de l’atmega32u4 avec la broche RX du convertisseur. Créer le fichier app_5/main.c


et y copier le programme ci-dessous. Compiler et programmer.
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
# define USART_BAUDRATE 9600
# define BAUD_PRESCALE F_CPU/USART_BAUDRATE/16 - 1

void uart_transmit( unsigned char data )


{ while ( ! (UCSR1A & (1 << UDRE1)) ); UDR1 = data;}

unsigned char uart_receive(void)


{ while (!( UCSR1A & ( 1 << RXC1) )); return UDR1;}

void uart_init(void)
{ unsigned int baud = BAUD_PRESCALE;
UBRR1H = (unsigned char) (baud >> 8 );
UBRR1L = (unsigned char)baud;
UCSR1B = ( 1 << RXEN1 ) | ( 1 << TXEN1 );
UCSR1C = ( 3 << UCSZ10 ) ;//8N1
UCSR1A = ( 1<<U2X1 );}
//int uart_dataAvailable(void);
int main(void)
{ CLKPR = 0x80; CLKPR = 0x00;//required for this teensy
MCUCR &=~(1<<PUD);// char c=42;
uart_init();
while (1)
{ _delay_ms(10); uart_transmit(c);
c++; if (c==127) {c=32;uart_transmit('\n');}}
return 0;
}
Q5.1 : Qu’affiche le code ci-dessus ? Quelle est la durée de transmission de chaque caractère ?
Q5.2 : Modifier le programme pour recevoir un caractère obtenu sur le port série, et le transformer en la
majuscule si le caractère reçu est une lettre minuscule, et réciproquement.

Master – Département GE – BABA 7 modifié le 29 Oct. 2024


Application 6 : Interruptions UART

Afin de libérer le CPU, il est souhaitable d’interrompre l’exécution séquentielle qu’un caractère est reçu.
Cependant, nous ne voulons pas passer de temps inutilement dans l’interruption qui doit se réduire
uniquement au code de réception d’un caractère. À ces fins, nous définissons un flag qui indique au
programme principal la réception d’un caractère et qu’une action doit être prise en conséquent.
Reprendre le code ci-dessous dans un nouveau projet. Compiler, programmer et tester.
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h> // _delay_ms
#define USART_BAUDRATE 9600
#define BAUD F_CPU/USART_BAUDRATE/16UL - 1

volatile unsigned char received;


volatile uint8_t flag=0;

ISR(USART1_RX_vect) {received=UDR1; flag=1;}

void uart_transmit( unsigned char data )


{ while ( ! (UCSR1A & (1 << UDRE1)) ); UDR1 = data;}

int main(void){
CLKPR = 0x80; CLKPR = 0x00;//required for this teensy
MCUCR &=~(1<<PUD);// char c=42;
DDRD |=1 << PORTD6;
PORTD |= 1 << PORTD6;
UCSR1A = 0; // importantly U2X1 = 0
unsigned int baud = BAUD;
UBRR1H = (unsigned char) (baud >> 8 );
UBRR1L = (unsigned char) baud;
UCSR1B = (1 << RXEN1) | (1 << TXEN1);
UCSR1C = (3 << UCSZ10);
UCSR1A = (1<<U2X1);

UCSR1B |= (1 << RXCIE1);

sei();
while (1)
if (flag!=0) {flag=0;uart_transmit(received);PORTD ^=(1<<PD6);}

return 0;
}

Q6.1 : Justifier de la définition de variables globales pour échanger des informations entre programme
principal et gestionnaire d’interruption.
Q6.2 : Proposer une solution pour recevoir plusieurs caractères entre deux traitements du flag par le
programme principal. Le traitement se fera dans la gestionnaire d’interruption.
Q6.3 : Proposer un code C qui fait clignoter une LED6 périodiquement, détecte une transition d’état sur
PB1, et communique par UART, en limitant la boucle infinie dans la fonction principale main() à while
(1); Penser à éliminer le flag et aussi la fonction uart_transmit (received).

Master – Département GE – BABA 8 modifié le 29 Oct. 2024

Vous aimerez peut-être aussi