Ayant obtenu des PIC18F4550 et 18F2550 en échantillons, j'ai décidé de les découvrir un peu plus.

L'environnement de développement est fourni par Microchip :

Ma plaque de test est on ne peut plus simple :

  • Un quartz à 12MHz avec ses 2 capacités
  • Le circuit de "Reset" composé d'une résistance et d'un condensateur
  • Une alimentation 5 Volts tirée directement du port USB.
  • Quelques résistances de Pull Up

Tous les exemples trouvés sur le web fontionne avec des quartz à 20 MHz, il suffit simplement de modifier les bits de configuration. J'utilise le mode HSPLL, c'est à dire High Speed with PLL enabled. En utilisant un quartz 12MHz, il faut configurer le diviseur pour diviser par 3 la fréquence d'horloge pour obtenir un 4MHz permettant de générer par la suite un 48MHz nécessaire pour la gestion USB. Il faut donc modifier la ligne :

#pragma config PLLDIV = 3

Utilisation du MSSP pour établir une communication I2C

Le PIC18f4550 peut être configurer pour établir une communication SPI, I2C maitre et esclave. L'utilisation est relativement simple. Il ne faut pas oublier de configurer les ports RB0 et RB1 en entrée tel qu'indiqué dans la documentation.

Le premier test a été d'allumer les célèbres leds connectées sur un PCF8574. Celui ci est configuré en adress 0x40.

Ouverture de la communication I2C

Il ne faut pas oublier de configurer les ports en entrées avant:

//RB0 et RB1 en entrées	
TRISBbits.TRISB0 = 1;
TRISBbits.TRISB1 = 1;

On utilise la fonction fournie par Microchip : OpenI2C()
Etant donné que l'on travaille en mode Master, il faut configurer la vitesse de la communication. La formule fournie par Microchip est la suivante :
clock = Fosc/(4*(SSPADD+1)).
On peut en tirer la formule suivante : SSPADD = ((Fosc/clock)/4)-1
Désirant travailler à une vitesse de 100 Kbits par secondes, et avec une vitesse interne de 48 MHz, il faut donc initialiser la valeur de SSPASS à 0x77.
SSPADD = ((48000000/100000)/4)-1 = (480/4)-1 = 120-1 = 119

Ecriture vers un composant I2C Slave

Voici la fonction utilisée pour écrire sur ce composant :

unsigned char Write(unsigned char cAddress, unsigned char cValue) 
{
   unsigned char bRet = 0x00;
   IdleI2C();	 //Attente du bus OK
   StartI2C();	 //Envoi de message de début
   IdleI2C();	 //Attente de la disponibilité du bus
   putcI2C(cAddress); //Envoi de l'adresse
   IdleI2C();	//Attenre de la disponibilité du bus
   if (SSPCON2bits.ACKSTAT) //Si AckStat == 1, on n'a pas reçu d'acquittement
   {
      StopI2C();  //Envoi de la condition de stop
      return bRet;
   } 
   putcI2C(cValue);	//On écrit la valeur
   IdleI2C();			//Attente de disponibilité du bus
   if (!SSPCON2bits.ACKSTAT ) //Si on reçoit un acquitement, on retourne 1
   {
      bRet = 0x01;
   }
   StopI2C();
   return bRet;
}

Pour écrire 0x0F sur ce composant, il suffit d'appeler la fonction Write(0x40,0x0F);

Lecture sur le bus I2C

La lecture du composant m'a posé plus de problème, mais c'est relativement simple quand même. Voici donc la fonction de lecture :

unsigned char Read(unsigned char cAddress)
{
   unsigned char bRet = 0x00;
   IdleI2C();	 //Attente du bus OK
   StartI2C();	 //Envoi de message de début
   IdleI2C();	 //Attente de la disponibilité du bus
   putcI2C(cAddress); //Envoi de l'adress
   IdleI2C();	//Attente de la disponibilité du bus
   if (SSPCON2bits.ACKSTAT) //Si AckStat == 1, on n'a pas reçu d'acquittement
   {
      StopI2C();  //Envoi de la condition de stop
      return bRet;
   }
   bRet = ReadI2C(); //Lecture I2C
   NotAckI2C();       //Pas d'acquittement car on lit qu'un seul caractère
   IdleI2C();
   StopI2C();          //Envoi du stop
   return bRet;        //Retour de la valeur lue
}