Je vais essayer d'être le plus precis possible. Je vais te donner deux codes, le premier sans fonction, le second avec fonction !
Pour commencer quand tu configures tes registres ADCON1 ; 2 et 3 tu peux configurers chaqu'un en une seule ligne, au lieu de faire du bit à bit, et donc un gain de temps ( notamment pour le temps de boucle).
1ére solution :
#include <p18f4520.h>
#define q 4.8828e-3
/* quantum (résolution) tu as un CAN 10bit, 2^10 =1024. Donc 1024 => 5V ; 1=> ???V soit 0.0048828... */
void main(void)
{
float AN0;
/CAN on. CLOCK=FOSC/2. CANAL0 (RA)
// VREF+=VDD VREF-=VSS
ADCON0=1;
/* les bits 7 et 6 du registre ADCON0 (pour le 18f4520) ne sont pas utilisés, les bits 5->2 servent a choisir quel CAN, ici on utilise le AN0 soit 000; le bit 1 est un bit d'etat, et le bit 0 est pour valider le fonctionnement. On aurait pu ecrire les codes suivants : ADCON0=0x01 ou 0b00000001 ce qui revient a ecrire 1 */
ADCON1=0x8E;
/* soit 1000 1110; le premier 1 sert a justifier a droite. Le E sert a configurer les pins. */
while(1){ // boucle infinie pour utiliser en continue, dnas le cas d'une seule conversion pas besoin, on aurait pu
// for (;;) ou encore for(;3.14;) un truc qui est vrai tout le temps !
ADCON0bits.GO_DONE=1; //lance la conversion
while(ADCON0bits.GO_DONE // attente de la fin de la conversion
AN0=(float)ADRES*q; // calcule du resultat.
}
}
A partir de la tu peux explorer comme tu veux AN0.
Solution inspirée du site de : www.aix-mrs.iufm.fr ( ils ont une page avec des tp sur la programmation du 18f4520)
La deuxieme solution, vient d'un de mes profs de l'iut de Cachan.
A mettre dans un fichier CAN.h
#include <p18f4520.h>
void adc_init(char Nb_CAN_use-1); // init du CAN
int adc_read(char CAN_choisi); // lecture de la valeur analogique d'un channel
A mettre dans un fichier CAN.c
#include "CAN.h"
// pour info : AN0 => a0 , AN1=>a1... AN5=>e03
void adc_init(char Nb_CAN_use-1)
{
switch(Nb_CAN_use-1) /*configure ADCON1 suivant le numero du dernier CAN, Par exemple tu veux utiliser cinq CAN tu ecris adc_init (4) */
{
case(0) : ADCON1 = 0xE; //configuration pour un CAN
TRISA = TRISA|0b00000001;
break;
case(1) : ADCON1 = 0xD;
TRISA = TRISA|0b00000011;
break;
case(2) : ADCON1 = 0xC;
TRISA = TRISA|0b00000111;
break;
case(3) : ADCON1 = 0xB;
TRISA = TRISA|0b00001111;
break;
case(4) : ADCON1 = 0xA;
TRISA = TRISA|0b00101111;
break;
case(5) : ADCON1 = 0x9;
TRISA = TRISA|0b00101111;
TRISE = TRISE|0b00000001;
break;
case(6) : ADCON1 = 0x8;
TRISA = TRISA|0b00101111;
TRISE = TRISE|0b00000011;
break;
case(7) : ADCON1 = 0x7;
TRISA = TRISA|0b00101111;
TRISE = TRISE|0b00000111;
break;
case(8) : ADCON1 = 0x6;
TRISA = TRISA|0b00101111;
TRISE = TRISE|0b00000111;
TRISB = TRISB|0b00000100;
case(9) : ADCON1 = 0x5; //configuration de 10 CAN
TRISA = TRISA|0b00101111;
TRISE = TRISE|0b00000111;
TRISB = TRISB|0b00001100;
default : ADCON1 = 0xF;
}
ADCON2 = 0b10100110; /*configure la Fconv (Fhorloge/64) + tps d'acqui +8periode de conv + justification a droit pour utiliser sur 10bits*/
ADCON0bits.ADON = 1; // valide l'utilisation du CAN
}
int adc_read(char CAN_choisi)
{
int resultat =0 ; //varible qui sera retournée
ADCON0 = ((numero_channel << 2) & 0b00111100) |
(ADCON0 & 0b11000011); // selection du channel (du CAN)
ADCON0bits.GO = 1; // Lancement de conversion
while(ADCON0bits.GO); // attendre la fin de la conversion
result = (int)ADRESH; // Read ADRESL into the lower byte
result = result<<8 | (int)ADRESL; // Read ADRESH into the high byte
return (result); // retourne la valeur
}
A mettre dans un main,
tu declares tes variables, puis tu les utilise par exemple:
Fichier main.c:
#include "CAN.h"
void main (void)
{
int AN0=0;
int AN1=0;
adc_init(0);
adc_init(1);
AN0=adc_read(0);
AN1=adc_read(1);
//ensuite tu fais ce que tu veux des valeurs AN0
}
je pence que tout y est, pour conclure si tu utilises un seul CAN, la premiere solution est la solution, si tu compte en utiliser plusieur ( par exemple dix comme je doit faire) les fonctions s'averent tres utilent pour allerger le code et le rendre plus compréhensible.
J'espere t'avoir aidé
Nico