Application

Souvent, les débutants ont du mal à configurer correctement l'horloge de leurs PIC, surtout les modèles complexes comme les PIC18, et au final ne savent pas très bien à quelle fréquence ils fonctionnent. Cela peut conduire à de bonnes séances d'arrachage de cheveux... Il peut donc être intéressant de vérifier la configuration de l'horloge avant toute chose.

Je vous propose d'utiliser la broche PORTB7, multiplexée avec PGD, donc connectée au canal 1 de l'analyseur, pour vérifier la fréquence d'horloge. L'idée est de faire exécuter une suite d'instructions dont on connaîtra précisément la longueur, entre des variations du signal sur PORTB7. Considérons le programme suivant, pour PIC18F2455/2550/4455/4550 :

#include <p18f2455.h>

#pragma config FOSC = INTOSC_XT  // activation de l'oscillateur interne
#pragma config PBADEN = OFF      // port B en I/O numériques
#pragma config MCLRE = OFF       // on n'utilise pas MCLR
#pragma config WDT = OFF         // pas de watchdog

void main() {
	OSCCON = 0x42;           // configuration de l'oscillateur
		// OSCCON<6:4> = 100 => oscillateur interne à 1 MHz
		// OSCCON<1:0> = 10  => sélection de l'oscillateur interne

	TRISB = 0;               // PORTB en sortie

boucle:
	PORTBbits.RB7 = 0; Nop(); Nop(); Nop(); Nop();
	PORTBbits.RB7 = 1; Nop(); Nop();
	goto boucle;	
}

La boucle va mettre PORTB7 à 1 une partie du temps, puis à 0 l'autre partie du temps. Pour savoir précisément combien de temps dure la boucle (en termes de cycles d'instruction), il faut absolument regarder le listing en langage machine, car le compilateur peut toujours ajouter des choses imprévues. Dans MPLAB, faire View → Diassembly Listing. Dans ce cas, il n'y a pas de surprise :

15:               boucle:
16:               	PORTBbits.RB7 = 0; Nop(); Nop(); Nop(); Nop();
  00C8    9E81     BCF 0xf81, 0x7, ACCESS
  00CA    0000     NOP
  00CC    0000     NOP
  00CE    0000     NOP
  00D0    0000     NOP
17:               	PORTBbits.RB7 = 1; Nop(); Nop();
  00D2    8E81     BSF 0xf81, 0x7, ACCESS
  00D4    0000     NOP
  00D6    0000     NOP
18:               	goto boucle;	
  00D8    D7F7     BRA 0x462

On a donc 5 instructions avec PORTB7 à 0 (en comptant le BCF, bit clear), puis 4 instructions avec PORTB7 à 1 (en comptant le BSF, bit set). Or, toutes les instructions du PIC s'exécutent en un cycle d'instruction, sauf celles qui affectent le compteur ordinal (PC), qui durent deux cycles lorsque le compteur ordinal est effectivement affecté. C'est ici le cas du BRA, qui durera deux cycles. Au final, on se trouve donc avec une boucle de 10 cycles d'instruction, donc 5 avec PORTB7 à 0, et 5 avec PORTB7 à 1.

Chargeons le programme dans le PIC, alimentons-le via le PICkit, et lançons l'analyseur (Tools → Logic Tool). Il faut configurer une condition de déclenchement, une fréquence, puis cliquer sur « Run ». On obtient alors un résultat du type suivant :

Outil analyseur logique du PICkit 2

On retrouve bien la forme de résultat attendue sur le canal 1. Le curseur (en bleu), permet d'aller mesurer des temps. On voit ainsi que le temps d'exécution de la boucle est de 41 µs. Cela correspond-il à la configuration prévue pour l'oscillateur ? 41 µs donne environ 4 µs par cycle d'instruction (souvenez-vous, 10 cycles dans la boucle). Or sur PIC, un cycle d'instruction correspond à 4 cycles de l'horloge du CPU. Cela amène donc le cycle d'horloge à 1 µs, ce qui correspond bien à la valeur voulue, 1 MHz.

Note sur l'utilisation de l'oscillateur interne des PIC18F2455/2550/4455/4550

Il ne suffit pas d'activer l'oscillateur interne avec les bits de configuration #pragma config FOSC = INTOSC_XT. Selon ma compréhension de la spec, cela se contente d'activer l'oscillateur interne. Il reste alors à la configurer et le sélectionner à l'aide du registre OSCCON :

  • avec OSCCON<6:4> on sélectionne la fréquence, ici 100 pour 1 MHz (voir datasheet). C'est la valeur par défaut.
  • avec OSCCON<1:0> on sélectionne l'oscillateur. Il faut mettre 10, sans quoi par défaut le PIC utilisera l'horloge primaire, c'est-à-dire celle générée à partir du quartz externe, ce qui n'est pas du tout ce que l'on veut. 10 sélectionne l'oscillateur interne.
  • les autres bits sont à laisser à 0.

Dans l'exemple ci-dessus, j'avais donc mis OSCCON à 0x42. Laissez toujours le nibble de droite à 2 en mode interne, et utilisez le nibble de gauche pour sélectionner la fréquence.