Dernière mise à jour le 30/12/2020

Présentation


Dans ce présent article, nous allons aborder la programmation d’un PIC18F4550 afin de pouvoir communiquer en I2C pour lire ou écrire sur une EEPROM 24C08 (cette d’ailleurs celle qui est livrée sur la platine EasyPic V7).
EEPROM est l’abréviation de Mémoire morte programmable effaçable électriquement. Il s’agit généralement d’une mémoire de stockage secondaire dans les appareils contenant des données qui sont conservées même si l’appareil perd son alimentation. En raison de la capacité de modifier des octets de données uniques, les dispositifs EEPROM sont utilisés pour stocker les préférences personnelles et les données de configuration dans un large éventail d’applications grand public, automobiles, de télécommunications, médicales, industrielles et PC. L’EEPROM série qui utilise l’interface de communication I2C dispose de 1024 octets de mémoire disponible. L’EEPROM prend en charge les opérations d’écriture et de lecture sur un octet ou sur 16 octets (page). Le débit de données est de 400 kHz pour les alimentations 3,3 V et 5 V.


Comme évoqué j’utilise le PIC18F4550 or, J’ai bien peur que vous me posiez la question du genre:

– “Pourquoi le faire un PIC18F4550 sachant que nous avons le 18F45K22 qui lui est aussi livré avec la platine ?


je vous répondrais :

– “Oui vous avez raison!

Or à ce jour j’ai oublié de le récupérer et je me suis retrouvé avec le PIC18F4550 au lieu du PIC18F45K22 de connecté sur ma platine …

Soft_I2C Logiciel (Software) ou I2C Matériel (Hardware) ?


Bonne question? mais qu’est ce que cela veux bien dire ?
Pour faire simple:


I2C Logiciel (Software) : Lorsque nous parlons de I2C Logiciel c’est que votre microcontrôleur ne possède pas les broches SDA et SDL alors il faut trouver une parade afin de créer ces 2 broches pour la communication par la méthode logiciel (Software) en programmant quelques lignes de code supplémentaires. (On utilise la routine Soft_I2C de MikroC).


I2C Matériel (Hardware) : Lorsque nous parlons de I2C Matériel, c’est que votre microcontrôleur possède les broches SDA et SDL. (On utilise la routine I2C1 de MikroC)


Voilà la différence entre les deux !! pas compliquer non? avec ou sans broches SDA et SDL il est tout à fait possible de communiquer par la liaison I2C mais je vous conseille si vous devez réaliser un programme un peu plus complexe en utilisant des interruptions, vérifier le Buffer, ou autres de vous garantir que le PIC que vous utilisez soit bien équipé des broches SDA/SDL.
Bon avec tous ces grands discours essayons de regarder ça de plus prêt en commençant par des choses simples on verra ensuite le compliquer.

Schéma – 001 (Ecriture sur Add 0x00)



Sur le schéma électronique, on y retrouve notre PIC18F4550 ainsi que notre EPPROM 24C08, ces deux composants sont reliés au +5V de l’alimentation à travers des résistances PULL-UP de 1K, et les broches SDA/SCL côté microcontrôleur sont reliées vers le 24C08 afin d’assurer la liaison I2C. Comme vous pouvez le constater, nul besoin d’utiliser la façon Logiciel (Software) car le 18F4550 a bien une liaison I2C matériel (Hardware) – voir plus haut la différence entre les 2 pour ceux qui auraient manqués

Programmation materiel – MikroC


// Ecriture/Lecture sur EEPROM 24C08 – MikroC – Electronique71.com

const c24C08B_Write = 0xA0; // correspond à l'adresse EEPROM pour ecriture
const c24C08B_Read = 0xA1;  // correspond à l'adresse EEPROM pour lecture

void Ecriture_EEPROM()
{
  I2C1_Start();           // Bit de start I2C
  I2C1_Wr(c24C08B_Write); // adresse EEPROM pour ecriture;
  I2C1_Wr(0x00);          // Ecriture sur le registre (adresse = 0x00)
  I2C1_Wr(0x01);          // Ecriture de la valeur 0x01
  I2C1_Stop();            // Bit de stop I2C
}

void Lecture_EEPROM()
{
  I2C1_Start();            // Bit de start I2C
  I2C1_Wr(c24C08B_Write);  // adresse EEPROM pour ecriture
  I2C1_Wr(0x00);           // Ecriture du registre à l'adresse 0x00
  I2C1_Repeated_Start();   // On répète le bit de start pour lancer la lecture
  I2C1_Wr(c24C08B_Read);   // adresse EEPROM pour lecture
  PORTD = I2C1_Rd(0);      // Lecture de l'adresse
  I2C1_Stop();             // Bit de stop I2C
}

void init()
{
  // On configure de toutes les broches en digital (numérique 0 ou 1)
  PCFG0_bit = 1;
  PCFG1_bit = 1;
  PCFG2_bit = 1;
  PCFG3_bit = 1;

  ADON_bit = 0;        // On désactive le module de convertion analogique/numérique

  TRISD = 0x00;        // Configuration PORTD en sortie pour la lecture
  PORTD = 0x00;
  LATD = 0x00;
  
  I2C1_Init(100000);   // Initialisation à 100Khz
  
  Delay_ms(500);       // On attend un peu la fin de l'initialisation
}

void main()
{
  init();

  while (1)
  {
    Ecriture_EEPROM(); // Ecriture dans l'EEPROM
    Delay_ms(1000);
    Lecture_EEPROM();  // Lecture de l'EEPROM
    Delay_ms(1000);
    PORTD = 0x00;      // On efface la lecture
  }
}

Ce code peut être copié et collé dans votre IDE. Pour ma part j’utilise MikroC de MikroElectronika, étant donné que je développe en C++ je me suis mis aussi à developpé en C afin de faire le duo C/C++ mais bien enttendu vous pouvez faire de même en MikroPascal.

Fonctionnement

Avant toute choses, assurez vous que sur le PIC18F4550 vous avez bien dans l’onglet “Project” – “Edit Project”, sélectionné dans “96Mhz PLL Prescaler” Divide by 2 (8Mhz input) car sur la platine EasyPic V7 un quartz de 8Mhz est en entrée, puis ne pas oublier de mettre le cavalier J19 sur MCLR ou bien laisser le cavalier J19 MCLR en position I/O mais par contre désactiver toujours dans “Edit – Project” vous rendre dans “Master Clear Enable” en selectionnant MCLR Disabled,RE3 Enabled.


j’ouvre une parenthèse, (vous aviez raison de me dire d’utiliser le PIC18F45K22 car j’étais dans l’obligation de créer des ponts avec des fils connecteurs entre RB0 et RC4 puis RB1 et RC3…) bon je la referme :-).


Si maintenant vous décidez de compiler le programme et de l’injecter dans le PIC18F4550 vous verrez que ce montage ne fais que de faire clignoter la led RD0.


Pour le programme je vous laisse le lire afin que vous puissiez bien comprendre comment celui-ci fonctionne (voir détails de chaque lignes)

Schéma – 002 (Ecriture sur Add 0x00 + Add 0x01 du registre)


Nous gardons toujours le même schéma, cependant nous allons cette fois-ci voir comment écrire sur 2 adresses différentes (Add 0x00 et Add 0x01). Regardons ensemble le programme ci-dessous:

Programmation materiel – MikroC


// Ecriture/Lecture sur EEPROM 24C08 – MikroC – Electronique71.com

const c24C08B_Write = 0xA0; // correspond à l’adresse EEPROM pour ecriture

const c24C08B_Read = 0xA1; // correspond à l’adresse EEPROM pour lecture

unsigned char Valeur_Add_0 = 0x0F; // Valeur adresse 0

unsigned char Valeur_Add_1 = 0xF0; // Valeur adresse 1

void Ecriture_Add_0_EEPROM()

{
  I2C1_Start();           // Bit de start I2C
  I2C1_Wr(c24C08B_Write); // adresse EEPROM pour ecriture;
  I2C1_Wr(0x00);          // Ecriture sur le registre (adresse = 0x00)
  I2C1_Wr(Valeur_Add_0);  // Ecriture de la valeur 0x0F
  I2C1_Stop();            // Bit de stop I2C
}

void Ecriture_Add_1_EEPROM()
{
  I2C1_Start();           // Bit de start I2C
  I2C1_Wr(c24C08B_Write); // adresse EEPROM pour ecriture;
  I2C1_Wr(0x01);          // Ecriture sur le registre (adresse = 0x01)
  I2C1_Wr(Valeur_Add_1);  // Ecriture de la valeur 0xF0
  I2C1_Stop();            // Bit de stop I2C
}

void Lecture_Add_0_EEPROM()

{
  I2C1_Start();           // Bit de start I2C
  I2C1_Wr(c24C08B_Write); // adresse EEPROM pour ecriture
  I2C1_Wr(0x00);          // Ecriture du registre (adresse 0x00)
  I2C1_Repeated_Start();  // On répète le bit start pour la lecture
  I2C1_Wr(c24C08B_Read);  // adresse EEPROM pour lecture
  PORTD = I2C1_Rd(0);     // Lecture de l’adresse
  I2C1_Stop();            // Bit de stop I2C
}

void Lecture_Add_1_EEPROM()
{

  I2C1_Start();            // Bit de start I2C
  I2C1_Wr(c24C08B_Write);  // adresse EEPROM pour ecriture
  I2C1_Wr(0x01);           // Ecriture du registre (adresse 0x01)
  I2C1_Repeated_Start();   // On répète le bit start pour la lecture
  I2C1_Wr(c24C08B_Read);   // adresse EEPROM pour lecture
  PORTD = I2C1_Rd(0);      // Lecture de l'adresse
  I2C1_Stop();             // Bit de stop I2C
}

void init()
{
  // On configure de toutes les broches en digital (numérique 0 ou 1)
  PCFG0_bit = 1;
  PCFG1_bit = 1;
  PCFG2_bit = 1;
  PCFG3_bit = 1;

  ADON_bit = 0; // On désactive le module de convertion analogique/numérique

  TRISD = 0x00;      // Configuration PORTD en sortie pour la lecture
  PORTD = 0x00;
  LATD = 0x00;
  
  I2C1_Init(100000); // Initialisation à 100Khz
  
  Delay_ms(500);     // On attend un peu la fin de l'initialisation
}

void main()
{
  init();

  while (1)
  {
    Ecriture_Add_0_EEPROM();  // Ecriture sur Add 0x00
    Delay_ms(100);            // On attend un peu la fin d'écriture
    Ecriture_Add_1_EEPROM();  // Ecriture sur Add 0x01
    Delay_ms(100);            // On attend un peu la fin d'écriture
    Lecture_Add_0_EEPROM();   // Lecture Add 0x00 -> Valeur 0x0F
    Delay_ms(1000);
    Lecture_Add_1_EEPROM();   // Lecture Add 0x01 -> Valeur 0xF0;
    Delay_ms(1000);
    PORTD = 0x00;             // On efface la lecture
  }
}

Ce code quant à lui fait clignoter 4 leds un coup RD0 à RD3 et un coup RD4 à RD7 tout simplement.

Test sur platine EasyPicV7


Différentes photos ou vous verrez le fameux pont sur les broches RB0 et RC4 puis RB1 et RC3, le principale c’est que le montage fonctionne on verra la finition plus tard !

Programmation logiciel – MikroC


Nous avons vue précédemment une programmation lorsque SDA/SCL est présent sur le microcontrôleur. Et vous savez quoi? même si le PIC18F4550 est doté côté materiel de broches SDA/SCL je vais quand même vous faire une démonstration version logiciel (Software) en utilisant la routine “Soft_I2C” afin que si un jour le PIC que vous utilisé ne comporte pas les broches SDA/SCL, que vous puissiez réaliser une liaison I2C. Tiens d’ailleur vous allez me demander si on peut doubler la liaison I2C? la réponse ? je pense que oui mais je n’ai jamais essayé à vrai dire… peut-être .. un jour…

Ce que je vous propose, c’est de regarder la programmation qui va suivre, alors allons voir ça de plus prêt!

Schéma – 001 (Ecriture sur Add 0x00) – Modification pour programmation Logiciel


Nous allons changer les broches de communication et nous allons prendre … Heu.. allez prenons RA1 et RA2 pour réaliser SCL/SDA. niveau montage cela donne ceci:


Jusqu’à ici rien de bien compliqué nous avons juste changé le câblage en faisant la connexion sur RA1 et RA2 (sans oublier bien sur de faire ce fameux pont de RA1 à RC3 puis RA2 à RC4 sur votre platine EasyPic V7 comme montré précédemment en photo….. et oui! il ne faut pas l’oublier 😉 Regardons côté logiciel ce qu’il change.

Programmation logiciel – MikroC


// Ecriture/Lecture sur EEPROM 24C08 – MikroC – Electronique71.com

// Software I2C
sbit Soft_I2C_Scl at RA1_bit; // Config broches RA1 en SCL
sbit Soft_I2C_Sda at RA2_bit; // Config broches RA2 en SDA
sbit Soft_I2C_Scl_Direction at TRISA1_bit;
sbit Soft_I2C_Sda_Direction at TRISA2_bit;

const c24C08B_Write = 0xA0; // correspond à l’adresse EEPROM pour ecriture
const c24C08B_Read = 0xA1; // correspond à l’adresse EEPROM pour lecture

void Ecriture_EEPROM()

{
  Soft_I2C_Start();              // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture
  Soft_I2C_Write(0x00);          // Ecriture sur le registre (adresse = 0x00)
  Soft_I2C_Write(0x01);          // Ecriture de la valeur 0x01
  Soft_I2C_Stop();               // Bit de stop I2C
}

void Lecture_EEPROM()
{
  Soft_I2C_Start();              // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture
  Soft_I2C_Write(0x00);          // Ecriture du registre
  Soft_I2C_Start();
  Soft_I2C_Write(c24C08B_Read);  // adresse EEPROM pour lecture
  PORTD = Soft_I2C_Read(0);      // Lecture de l’adresse
  Soft_I2C_Stop();               // Bit de stop I2C
}

void init()

{
  // On configure de toutes les broches en digital (numérique 0 ou 1)
  PCFG0_bit = 1;
  PCFG1_bit = 1;
  PCFG2_bit = 1;
  PCFG3_bit = 1;

  ADON_bit = 0; // On désactive le module de convertion analogique/numérique

  TRISD = 0x00; // Configuration PORTD en sortie pour la lecture
  PORTD = 0x00;
  LATD = 0x00;

  Soft_I2C_Init(); // Initialisation

  Delay_ms(500); // On attend un peu la fin de l’initialisation
}

void main()

{
  init();

  while (1)
  {
    Ecriture_EEPROM();
    Delay_ms(1000); // On attend un peu la fin d’écriture
    Lecture_EEPROM();
    Delay_ms(1000);
    PORTD = 0x00; // On efface la lecture

  }

}

Le fonctionnement est identique au Schéma – 001 (Ecriture sur Add 0x00) – je vous laisse relire ce paragraphe pour plus d’explication

Schéma – 002 (Ecriture sur Add 0x00 + Add 0x01 du registre) – Modification pour programmation Logiciel


Programmation logiciel – MikroC


Pour finir sur le 2ème exemple côté logiciel, le fonctionnement est identique je vous laisse voir le détails au niveau du Schéma – 002 (Ecriture sur Add 0x00 + Add 0x01 du registre). Par contre regardons les changements niveau programmation côté Logiciel (Software)

// Ecriture/Lecture sur EEPROM 24C08 – MikroC – Electronique71.com

// Software I2C

sbit Soft_I2C_Scl at RA1_bit; // Config broches RA1 en SCL
sbit Soft_I2C_Sda at RA2_bit; // Config broches RA2 en SDA
sbit Soft_I2C_Scl_Direction at TRISA1_bit;
sbit Soft_I2C_Sda_Direction at TRISA2_bit;

const c24C08B_Write = 0xA0; // correspond à l’adresse EEPROM pour ecriture

const c24C08B_Read = 0xA1; // correspond à l’adresse EEPROM pour lecture

unsigned char Valeur_Add_0 = 0x0F; // Valeur adresse 0

unsigned char Valeur_Add_1 = 0xF0; // Valeur adresse 1

void Ecriture_Add_0_EEPROM()

{
  Soft_I2C_Start();               // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture;
  Soft_I2C_Write(0x00);          // Ecriture sur le registre (adresse = 0x00)
  Soft_I2C_Write(Valeur_Add_0);  // Ecriture de la valeur 0x0F
  Soft_I2C_Stop();               // Bit de stop I2C
}

void Ecriture_Add_1_EEPROM()
{
  Soft_I2C_Start();              // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture;
  Soft_I2C_Write(0x01);          // Ecriture sur le registre (adresse = 0x01)
  Soft_I2C_Write(Valeur_Add_1);  // Ecriture de la valeur 0xF0
  Soft_I2C_Stop();               // Bit de stop I2C
}

void Lecture_Add_0_EEPROM()

{
  Soft_I2C_Start();              // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture
  Soft_I2C_Write(0x00);          // Ecriture du registre (adresse 0x00)
  Soft_I2C_Start();              // On répète le bit start pour la lecture
  Soft_I2C_Write(c24C08B_Read);  // adresse EEPROM pour lecture
  PORTD = Soft_I2C_Read(0);      // Lecture de l’adresse
  Soft_I2C_Stop();               // Bit de stop I2C
}

void Lecture_Add_1_EEPROM()
{

  Soft_I2C_Start();              // Bit de start I2C
  Soft_I2C_Write(c24C08B_Write); // adresse EEPROM pour ecriture
  Soft_I2C_Write(0x01);          // Ecriture du registre (adresse 0x01)
  Soft_I2C_Start();              // On répète le bit start pour la lecture
  Soft_I2C_Write(c24C08B_Read);  // adresse EEPROM pour lecture
  PORTD = Soft_I2C_Read(0);      // Lecture de l'adresse
  Soft_I2C_Stop();               // Bit de stop I2C
}

void init()
{
  // On configure de toutes les broches en digital (numérique 0 ou 1)
  PCFG0_bit = 1;
  PCFG1_bit = 1;
  PCFG2_bit = 1;
  PCFG3_bit = 1;

  ADON_bit = 0;       // On désactive le module de convertion analogique/numérique

  TRISD = 0x00;       // Configuration PORTD en sortie pour la lecture
  PORTD = 0x00;
  LATD = 0x00;
  
  Soft_I2C_Init();   // Initialisation
  
  Delay_ms(500);     // On attend un peu la fin de l'initialisation
}

void main()
{
  init();

  while (1)
  {
    Ecriture_Add_0_EEPROM();  // Ecriture sur Add 0x00
    Delay_ms(100);            // On attend un peu la fin d'écriture
    Ecriture_Add_1_EEPROM();  // Ecriture sur Add 0x01
    Delay_ms(100);            // On attend un peu la fin d'écriture
    Lecture_Add_0_EEPROM();   // Lecture Add 0x00 -> Valeur 0x0F
    Delay_ms(1000);
    Lecture_Add_1_EEPROM();   // Lecture Add 0x01 -> Valeur 0xF0;
    Delay_ms(1000);
    PORTD = 0x00;             // On efface la lecture
  }
}

Si vous copié collé ce code vous derviez aussi voir les 4 leds clignoter un coup RD0 à RD3 et un coup RD4 à RD7 comme le code précédemment.

Test sur platine EasyPicV7


Est-ce bien la peine de reprendre les mêmes photos ? le fonctionnement est identique, par contre les connexions quant à elles sont différents bien faire le pont de RA1 à RC3 puis RA2 à RC4

Historiques


30/12/2020
-1er mise à disposition