Depuis quelque temps, le logiciel de programmation du PICkit 2 dispose d’une fonction analyseur logique et UART, extrêmement pratique. Intéressons-nous tout d’abord à l’analyseur logique. Il peut analyser trois canaux en parallèle, sur les broches PGC, PGD et AUX du PICkit 2. Ce qui est génial, c’est que les broches PGD et PGC sont déjà connectées sur tous les montages qui supportent la programmation sur place (ICSP), et qu’elles sont à ma connaissance multiplexées sur tous les PIC avec des I/O numériques. De plus, on essaie en général de ne pas utiliser les I/O multiplexées avec PGD et PGC, donc il y a de fortes chances que ces pins soient inutilisées dans le montage, et qu’on puisse donc les réquisitionner pour faire du débug sur les signaux ! Sans modifier un montage existant, sans déplacer le PICkit entre la phase de programmation et la phase d’exécution du programme, on peut donc analyser des signaux émis par le programme. Pratique, non ?
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 :
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.
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
:
OSCCON<6:4>
on sélectionne la fréquence, ici 100 pour 1 MHz (voir datasheet). C’est la valeur par défaut.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.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.