« SE4Binome2023-10 » : différence entre les versions

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Ligne 319 : Ligne 319 :
La mise à jour du curseur dépend de la valeur de '''data''' et si elle vaut l'un des caractère de contrôle, le curseur se mettra à jour sur la ligne suivante grâce à la fonction <code>'''lcdMoveCursor(pos.current_y, 0)'''</code>
La mise à jour du curseur dépend de la valeur de '''data''' et si elle vaut l'un des caractère de contrôle, le curseur se mettra à jour sur la ligne suivante grâce à la fonction <code>'''lcdMoveCursor(pos.current_y, 0)'''</code>
[[Fichier:Retour_chariot_et_à_la_ligne.jpg|alt=Gestion /n et /r|centré|246x246px]]
[[Fichier:Retour_chariot_et_à_la_ligne.jpg|alt=Gestion /n et /r|centré|246x246px]]
Pour initialiser l'écran LCD, nous avons écris la fonction suivante
Pour initialiser l'écran LCD, nous avons écris la fonction suivante
Pour initialiser l'écran LCD, nous avons écris la fonction suivante
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">

Version du 17 janvier 2024 à 11:24

Ordonnanceur / Système d'exploitation

Réalisation du Shield

Séance 13/09 : Parmi les activités disponibles, nous avons soudé le régulateur de tension, le lecteur SD, les résistances liées aux LEDs. Nous avons réalisé 2 câbles pour les cartes filles et un adaptateur.

carte Shield après première soudure
câbles
Adaptateur.jpg


Séance 19/09 : Durant cette séance nous avons soudé les autres résistances et les connecteurs. Et nous avons testé le bon fonctionnement de la carte Shield.

Voici la carte Shield soudé :

Photo de la carte Shield soudé

Nous avons soudé cette carte :

20230919.jpg

Pour le test nous avons utilisé le code qui est disponible sur le git. Voici ci-dessous une vidéo montrant le clignotement des LEDs.

Clignotement des LEDs avec ordonnanceur

Au cours de la fabrication de notre carte, nous avons commencé la réalisation de l'ordonnanceur.

Pour réaliser l'ordonnanceur, nous avons besoin d'une fonction de gestion d'interruption ISR qui sera déclenché par l'interruption.

ISR(TIMER1_COMPA_vect, ISR_NAKED) {
     SAVE_REGISTERS();
  
     taches[current].pointer_pile = SP;

     // Appel à l'ordonnanceur
     scheduler();
  
    SP = taches[current].pointer_pile;

     RESTORE_REGISTERS();
     asm volatile ( "reti" );
 }

Le principe c'est de créer deux tâches pour faire clignoter deux LEDs du bouclier avec des périodes différentes. La première tache allume et éteint une LED toutes les 200ms, la deuxième tache réalise la même opération sur une LED différente toutes les 1000ms.

 // Tâche 1
void task_LED_1() {
    DDRD |= (1 << LED4_PIN);
    PORTD &= ~(1 << LED4_PIN);

    while (1) {
        PORTD ^= (1 << LED4_PIN);
        _delay_ms(200); // Fréquence 200 ms
    }
}
  
 // Tâche 2
void task_LED_2() {
    DDRC |= (1 << LED1_PIN);
    PORTC &= ~(1 << LED1_PIN);

    while (1) {
        PORTC ^= (1 << LED1_PIN);
        _delay_ms(1000); // Fréquence 1000 ms
    }
}

Et voici la fonction permettant d'initialiser le contexte de chaque tâche :

void init_task(int id)
{
    uint16_t save_sp = SP;
    SP= taches[id].pointer_pile;

    uint16_t adresse=(uint16_t)taches[id].task_func;
    asm volatile("push %0" : : "r" (adresse & 0x00ff) );
    asm volatile("push %0" : : "r" ((adresse & 0xff00)>>8) );
    SAVE_REGISTERS();

    taches[id].pointer_pile = SP;
    SP = save_sp;
}

Afficheur 7 segments

Pour l'afficheur 7 segments, nous l'avons dans un premier temps fait sans ordonnancement pour connaitre sa fonctionnalité. Pour le tester on a juste affiché "1 2 3 4" sur l'afficheur comme indiqué sur l'image ci-dessous :

void afficheur(void)
{
     spi_activer();
     spi_exch(0x76);
     spi_desactiver();
    char seg[4] = "1234";
     while(1){
         spi_activer();
         for(uint8_t i = 0; i < 4 ; i++)
        {
            spi_exch(seg[i]);
        }

        _delay_ms(1000);
        spi_desactiver();
    }
}
Afficheur.jpg

Pour l'ordonnancement, nous l'avons testé sur l'afficheur 7 segments avec lecture/écriture sur le port série :

// fonction pour afficheur 7 segments
void afficheur(void)
{
    pause_smp(SEMAPHORE_SPI);
    spi_activer(SS_3);
    spi_exch(0x76);
    spi_desactiver(SS_3);

    while(1){
        for(int i = 0; i < 4 ; i++)
        {
            spi_activer(SS_3);
            spi_exch(caractere);
        }

         spi_desactiver(SS_3);
         _wait_ms(5);
        liber_smp(SEMAPHORE_SPI);
    }
}

Carte FPGA / VHDL

Carte électronique numérique

Type de carte choisie

La carte fille écran LCD.

Elle se compose :

  • d'un ATMega328p
  • d'un écran LCD à base de contrôleur HD44780
  • d'un connecteur HE10
  • d'un connecteur AVR ISP pour programmer le microcontrôleur
  • d'un potentiomètre pour régler la luminosité des cristaux liquides
  • d'un bouton switch pour le reset

Réalisation de la carte

Séance 22/09 : Durant cette séance nous avons commencé la schématique de notre carte.

Voici le schéma électronique de notre carte fille LCD :

Schematic de la carte fille LCD

Séance 03/10 : nous avons commencé le routage.

Séance 17/10 : routage terminé

Après le routage nous avons obtenu :

Routage1.png


Séance 24/10 :

Le routage terminé, le prof a vérifié le routage final et nous avons envoyé la carte afin de l'imprimer.

Durant cette même séance nous avons commencer la programmation de l'ordonnancement.

routage fini

Voici une vue 3D de ce qui va se trouver au dessus de notre carte. Notre écran se trouvera donc en dessous.

vue 3D

Présentation de la carte fille LCD

Séance 14/11 :

Nous avons reçu la carte, nous avons commencé la soudure des composants nécessaires pour un premier test de la carte.

  • Le microprossesseur
  • une led
  • L'horloge
Crte électronique.jpg
Crte soudée.jpg

Pour vérifier le bon fonctionnement de la carte, nous avons mis une led afin de savoir la fonctionnalité de la carte.

Pour cela, on a testé avec le code exemple présent Arduino IDE.

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(7, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(7, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

Nous avons soudé le reste des composants ainsi que l'écran LCD.

  • Le potentiomètre
  • le bouton reset
  • les connecteurs
  • l'écran LCD
  • Les capacités

Voici tous la présentation de tous les composants de notre carte fille :

carte soudée

Test de l'ecran avec Aduino IDE

test lcd

Nous avons testé le lcd avec le code qui est présent sur Arduino IDE en utilisant le bus SPI. Voici le code utilisé:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = A0, en = A2, d4 = 4, d5 = 5, d6 = 9, d7 = 10;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  pinMode(A1,OUTPUT);
  digitalWrite(A1,LOW);
  delay(1000);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
  pinMode(7,OUTPUT);
  digitalWrite(7,HIGH);
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

LCD avec SPI

Lors de la programmation de la carte fille, nous avons constaté que les pins du CS et de B7 de l'écran LCD devaient s'inter-changer sinon la communication SPI ne sera pas fonctionnelle.

Nous avons donc procéder avec le professeur la modification des pins.

Piste à découper.jpg

Nous avons couper la piste du pin 14 et le relier avec le "via" connecté à CS avec un fil. Puis relier le pin 10 avec B7 de l'écran LCD.

Carte avec inter-changement des pins B7 et CS

Programmation de la carte fille LCD

Les broches nécessaire à la programmation de l'écran LCD :

  • RS (Register Select)
  • EN (Enable)
  • R/W (Read/Write)
  • DB4 à DB7

Ecriture sur la carte LCD

La fonction lcdWrite4bits est conçue pour écrire quatre bits de données sur l’écran LCD en utilisant une interface 4 bits.

void lcdWrite4bits(uint8_t data, uint8_t rs){

    if(rs)
        LCD_RS_ON();
    else
        LCD_RS_OFF();

    LCD_RW_OFF();

    LCD_EN_ON();
     _delay_us(1);

    if(data & 1)
        LCD_DB4_ON();
    else
        LCD_DB4_OFF();

    if(data & 2)
        LCD_DB5_ON();
    else
        LCD_DB5_OFF();

    if(data & 4)
        LCD_DB6_ON();
    else
        LCD_DB6_OFF();

    if(data & 8)
         LCD_DB7_ON();
    else
        LCD_DB7_OFF();


    LCD_EN_OFF();
    _delay_us(1);
}

- rs indique si les données à écrire sont des données :

  • d'instruction « 0 »
  • des données à afficher « 1 »

- Les blocs de if testent chaque bit dans data. Ils activent ou désactivent les lignes de données (DB4 à DB7).

Gestion des caractères de contrôle et initialisation LCD

La fonction lcdWrite8bits est conçue pour écrire une valeur de 8 bits de data sur l'écran LCD. Pour la gestion du retour à la ligne et le retour chariot il faut vérifier si le caractère data est égal à un retour à la ligne \n ou un retour chariot \r.

 if ((data == '\n') || (data == '\r')) {
        pos.current_x = 0;
        pos.current_y = (pos.current_y + 1) % NB_LIGNE;
        lcdMoveCursor(pos.current_y, 0);
        return;
    }

La mise à jour du curseur dépend de la valeur de data et si elle vaut l'un des caractère de contrôle, le curseur se mettra à jour sur la ligne suivante grâce à la fonction lcdMoveCursor(pos.current_y, 0)

Gestion /n et /r

Pour initialiser l'écran LCD, nous avons écris la fonction suivante

Pour initialiser l'écran LCD, nous avons écris la fonction suivante

void lcdInit(){

    LCD_RS_INIT();
    LCD_EN_INIT();
    LCD_RW_INIT();
    LCD_DB4_INIT();
    LCD_DB5_INIT();
    LCD_DB6_INIT();
    LCD_DB7_INIT();

    _delay_ms(1);

    lcdWrite8bits(0x28,0); //4bits, 2 lignes
    lcdWrite8bits(0x08,0); //LCD off
    lcdWrite8bits(0x01,0); //Clear LCD

    _delay_ms(2);
    lcdWrite8bits(0x06,0); //incrementation
    lcdWrite8bits(0x0c,0);
}
  • lcdWrite8bits(0x0c, 0) : Allume l'écran LCD sans afficher le curseur.

Affichage des caractères

Pour afficher chaque caractère on a écris la fonction lcdPutc

void lcdPutc(char c){
    busy = 1;
    lcdWrite8bits(c,1);
    busy = 0;
}

busy à 1 est utilisé pour indiquer l'état de l'écran LCD s'il est en train de traiter une opération

GIT

Voici le lien du git : https://archives.plil.fr/handrian/projet_pico.git