SE4Binome2024-3
		
		
		
		Aller à la navigation
		Aller à la recherche
		
Réalisation d'un shield arduino
Schématique
Routage
PINOUT
| LED1 | PC0 | 
| LED2 | PC3 | 
| LED3 | PD1 | 
| LED4 | PD4 | 
| LED5 | PD7 | 
Brasage du shield
shield nu
shield fini
Test du shield
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,Serial_Led,0},
    {0x600, LED1_blink,0},
    {0x500, Serial_Message,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();
USART_Init(MYUBRR);
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 FOSC 16000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#define LED1 PC0
#define LED2 PC3
#define LED3 PD1
#define LED4 PD4
#define LED5 PD7
#define NB_TASKS 3
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 USART_Init(unsigned int ubrr);
void LED1_blink(void);
void LED2_blink(void);
void LED3_blink(void);
void LED4_blink(void);
void LED5_blink(void);
void USART_Transmit(unsigned char data);
unsigned char USART_Receive(void);
void Serial_Led();
void Serial_Message();
#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 USART_Init(unsigned int ubrr)
{
/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/*Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
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);
    }
}
void Serial_Led(){
    while(1){
        if(USART_Receive() == 'a') LED2_blink();
    }
}
void Serial_Message(){
    unsigned char data;
    while(1){
         data = USART_Receive();
        USART_Transmit(data);
    }
}
void USART_Transmit(unsigned char data)
{
/* Wait for empty transmit buffer */
while (!(UCSR0A & (1<<UDRE0)))
;
/* Put data into buffer, sends the data */
UDR0 = data;
}
unsigned char USART_Receive(void)
{
/* Wait for data to be received */
while (!(UCSR0A & (1<<RXC0)))
;
/* Get and return received data from buffer */
return UDR0;
}
Exemple d'utilisation
Clignotement de 5 Leds asynchrones
Liens
Lien du git : https://gitea.plil.fr/vdetrez/SE4_PICO_DETREZ_CART




