SE4Binome2024-3

De projets-se.plil.fr
Aller à la navigation Aller à la recherche

Réalisation d'un shield arduino

Schématique

Schematique shield CART DETREZ.pdf

Routage

Routage shield CART DETREZ.png

PINOUT

LED1 PC0
LED2 PC3
LED3 PD1
LED4 PD4
LED5 PD7

Brasage du shield

shield nu

Shield nu CART DETREZ 2.jpg

shield fini

Shield fini CART DETREZ.jpg

Test du shield

Affichage 7 segments DETREZ CART.jpg

Programmation ordonnanceur

Code ordonnanceur

#include "Fonctions.h"

#define RESTORE_REGISTERS() \
asm volatile ( \
    "pop r31 \n\t" \
    "pop r30 \n\t" \
    "pop r29 \n\t" \
    "pop r28 \n\t" \
    "pop r27 \n\t" \
    "pop r26 \n\t" \
    "pop r25 \n\t" \
    "pop r24 \n\t" \
    "pop r23 \n\t" \
    "pop r22 \n\t" \
    "pop r21 \n\t" \
    "pop r20 \n\t" \
    "pop r19 \n\t" \
    "pop r18 \n\t" \
    "pop r17 \n\t" \
    "pop r16 \n\t" \
    "pop r15 \n\t" \
    "pop r14 \n\t" \
    "pop r13 \n\t" \
    "pop r12 \n\t" \
    "pop r11 \n\t" \
    "pop r10 \n\t" \
    "pop r9 \n\t" \
    "pop r8 \n\t" \
    "pop r7 \n\t" \
    "pop r6 \n\t" \
    "pop r5 \n\t" \
    "pop r4 \n\t" \
    "pop r3 \n\t" \
    "pop r2 \n\t" \
    "pop r1 \n\t" \
    "pop r0 \n\t" \
    "out __SREG__, r0 \n\t" \
    "pop r0 \n\t" \
);

#define SAVE_REGISTERS() \
asm volatile ( \
    "push r0 \n\t" \
    "in r0, __SREG__ \n\t" \
    "push r0 \n\t" \
    "push r1 \n\t" \
    "push r2 \n\t" \
    "push r3 \n\t" \
    "push r4 \n\t" \
    "push r5 \n\t" \
    "push r6 \n\t" \
    "push r7 \n\t" \
    "push r8 \n\t" \
    "push r9 \n\t" \
    "push r10 \n\t" \
    "push r11 \n\t" \
    "push r12 \n\t" \
    "push r13 \n\t" \
    "push r14 \n\t" \
    "push r15 \n\t" \
    "push r16 \n\t" \
    "push r17 \n\t" \
    "push r18 \n\t" \
    "push r19 \n\t" \
    "push r20 \n\t" \
    "push r21 \n\t" \
    "push r22 \n\t" \
    "push r23 \n\t" \
    "push r24 \n\t" \
    "push r25 \n\t" \
    "push r26 \n\t" \
    "push r27 \n\t" \
    "push r28 \n\t" \
    "push r29 \n\t" \
    "push r30 \n\t" \
    "push r31 \n\t" \
);

int currentTask = 0;
//uint16_t SP = 0x700;

// FONCTIONS

// Déclaration des différentes tâches
process task[NB_TASKS] = {
    {0x700,LED1_blink,0},
    {0x600, LED2_blink,0},
    {0x500, LED3_blink,0},
    {0x400, LED4_blink,0},
    {0x300, LED5_blink,0}
};

void init_pile(int N){
    uint16_t tempSP = SP;
    SP = task[N].stackPointer;
    uint16_t adresse=(uint16_t)task[N].addressFunction;
    asm volatile("push %0" : : "r" (adresse & 0x00ff) );
    asm volatile("push %0" : : "r" ((adresse & 0xff00)>>8) );
    SAVE_REGISTERS();
    task[N].stackPointer = SP;
    SP = tempSP;
}

void init_minuteur(int diviseur,long periode){
TCCR1A=0;               // Le mode choisi n'utilise pas ce registre
TCCR1B=(1<<CTC1);       // Réinitialisation du minuteur sur expiration
switch(diviseur){
  case    8: TCCR1B |= (1<<CS11); break;
  case   64: TCCR1B |= (1<<CS11 | 11<<CS10); break;
  case  256: TCCR1B |= (1<<CS12); break;
  case 1024: TCCR1B |= (1<<CS12 | 1<<CS10); break;
  }
// Un cycle prend 1/F_CPU secondes.
// Un pas de compteur prend diviseur/F_CPU secondes.
// Pour une periode en millisecondes, il faut (periode/1000)/(diviseur/F_CPU) pas
// soit (periode*F_CPU)/(1000*diviseur)
OCR1A=F_CPU/1000*periode/diviseur;  // Calcul du pas
TCNT1=0;                // Compteur initialisé
TIMSK1=(1<<OCIE1A);     // Comparaison du compteur avec OCR1A
}

void scheduler(){
    currentTask ++;
    if(currentTask == NB_TASKS) currentTask = 0; // ordonnanceur en mode Round Robin
}

// Déclaration d'un tableau de processus
ISR(TIMER1_COMPA_vect, ISR_NAKED){    // Procédure d'interruption
/* Sauvegarde du contexte de la tâche interrompue */
SAVE_REGISTERS();
task[currentTask].stackPointer = SP;
/* Appel à l'ordonnanceur */
scheduler();
/* Récupération du contexte de la tâche ré-activée */
SP = task[currentTask].stackPointer;
RESTORE_REGISTERS();
asm volatile ( "reti" );
}

int main(void){
cli();
LED_init();
init_minuteur(256,PERIODE);
for(int i=1;i<NB_TASKS;i++) init_pile(i);
SP = task[0].stackPointer;
sei();
task[0].addressFunction();
}

Code des tâches

#ifndef FONCTIONS_H
#define FONCTIONS_H

// Inclusions de bibliothèques nécessaires
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <util/delay.h>

#define CTC1            WGM12           // Meilleur nom pour le bit

#define PERIODE         20

#define LED1 PC0
#define LED2 PC3
#define LED3 PD1
#define LED4 PD4
#define LED5 PD7

#define NB_TASKS 5

typedef struct process{
    uint16_t stackPointer; // stack pointer, défini le début du process
    void (*addressFunction)(void); // adresse de l'instruction en cours
    int state; // état de la fonction (prêt, en cours, terminé)
}process;

void LED_init(void);
void LED1_blink(void);
void LED2_blink(void);
void LED3_blink(void);
void LED4_blink(void);
void LED5_blink(void);

#endif
#include "Fonctions.h"

void LED_init(){
    DDRC |= (1<<LED1) | (1<<LED2);
    DDRD |= (1<<LED3) | (1<<LED4) | (1<<LED5);
    PORTC |= (1<<LED1)|(1<<LED2);
    PORTD |= (1<<LED3)|(1<<LED4)|(1<<LED5);
}

void LED1_blink(){
    while(1){
        PORTC ^= (1<<LED1);
        _delay_ms(150);
    }
}

void LED2_blink(){
    while(1){
        PORTC ^= (1<<LED2);
        _delay_ms(100);
    }
}

void LED3_blink(){
    while(1){
        PORTD ^= (1<<LED3);
        _delay_ms(250);
    }
}

void LED4_blink(){
    while(1){
        PORTD ^= (1<<LED4);
        _delay_ms(350);
    }
}

void LED5_blink(){
    while(1){
        PORTD ^= (1<<LED5);
        _delay_ms(50);
    }
}

Exemple d'utilisation

Clignotement de 5 Leds asynchrones

Liens

Lien du git : https://gitea.plil.fr/vdetrez/SE4_PICO_DETREZ_CART