Conversion A/D PIC18F4520
Mkv
Messages postés
8
Statut
Membre
-
Biggie -
Biggie -
Bonjour à vous !
Je voudrai réaliser un programme permettant une conversion analogique numerique avec un PIC 18F4520. J'utilise le logiciel et une carte de test MPLAB V8 avec MCC18.
Il faudrait donc un programme avec une initialisation de l'adc ainsi que le programme de conversion.
J'ai essayé l'initialisation ce qui donne ceci (Mon probleme est que j'ai très peu de base en langage C :'( ) :
Pourriez vous me dire ce qui ne va pas dans le bout de programme ci-dessus ? les choses à modifier ect ...
Pour la suite (conversion), je ne sais pas du tout comment faire ...
Je voudrai réaliser un programme permettant une conversion analogique numerique avec un PIC 18F4520. J'utilise le logiciel et une carte de test MPLAB V8 avec MCC18.
Il faudrait donc un programme avec une initialisation de l'adc ainsi que le programme de conversion.
J'ai essayé l'initialisation ce qui donne ceci (Mon probleme est que j'ai très peu de base en langage C :'( ) :
#include <p18f4520.h>
#include <adc.h>
void main(void)
{
TRISA=1; // PORTA en Entrée
PORTA=1; // PORTA a 1
ADCON0bits.ADON = 1 ; // A/D convert ON
ADCON0bits.CHS0 = 0 ; // Choisir la voie a convertir => AN0
ADCON0bits.CHS1 = 0 ; // Choisir la voie a convertir => AN0
ADCON0bits.CHS2 = 0 ; // Choisir la voie a convertir => AN0
ADCON0bits.CHS3 = 0 ; // Choisir la voie a convertir => AN0
ADCON1bits.PCFG0 = 1 ; // Configuration des ports A/D = AN1 et AN0
ADCON1bits.PCFG1 = 0 ; // Configuration des ports A/D = AN1 et AN0
ADCON1bits.PCFG2 = 1 ; // Configuration des ports A/D = AN1 et AN0
ADCON1bits.PCFG3 = 1 ; // Configuration des ports A/D = AN1 et AN0
ADCON1bits.VCFG0 = 0 ; // references de tension a utiliser par le CAN => Vref+ = Vdd
ADCON1bits.VCFG1 = 0 ; // references de tension a utiliser par le CAN => Vref- = Vss
ADCON2bits.ADCS0 = 0 ; // configurer horloge selection
ADCON2bits.ADCS1 = 0 ; // configurer horloge selection
ADCON2bits.ADCS2 = 1 ; // configurer horloge selection
ADCON2bits.ACQT0 = 0 ; // configurer un temps d'acquisition
ADCON2bits.ACQT1 = 0 ; // configurer un temps d'acquisition
ADCON2bits.ACQT2 = 0 ; // configurer un temps d'acquisition
ADCON2bits.ADFM = 1 ; // justification a droite
ADRESH=0x00 ; // Mise à zero du registre ADRESH
ADCON0bits.GO_DONE = 1; // A/D conversion in progress (Start Of Conversion)
while(ADCON0bits.GO_DONE); // Attente de l'EOC
{
ADCON0bits.GO_DONE=0; // EOC
X=ADRESH;
X<<=8;
X|=ADRESL;
}
Pourriez vous me dire ce qui ne va pas dans le bout de programme ci-dessus ? les choses à modifier ect ...
Pour la suite (conversion), je ne sais pas du tout comment faire ...
A voir également:
- Conversion A/D PIC18F4520
- Logiciel gratuit conversion calendrier républicain - Télécharger - Études & Formations
- 2k€ conversion ✓ - Forum Bureautique
- Conversion bytes en mo ✓ - Forum Webmastering
- Une personne bloqué sur snapchat peut accéder à la conversation ✓ - Forum Snapchat
- Combien de Bytes pour 1Mo ? ✓ - Forum Programmation
11 réponses
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
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
merci baucoup, j'y voie deja plus claire :)
cepandant, j'aimerais savoir, le 18f45020 dispose de 2 registres ADRESH et ADRESL , a quoi servent ils ?
Dans ta premiere solution quand tu ecris "AN0=(float)ADRES*q; // calcule du resultat. " cela veux dire quoi ? qu'il met le resultat de la conversion dans un registre ?
cepandant, j'aimerais savoir, le 18f45020 dispose de 2 registres ADRESH et ADRESL , a quoi servent ils ?
Dans ta premiere solution quand tu ecris "AN0=(float)ADRES*q; // calcule du resultat. " cela veux dire quoi ? qu'il met le resultat de la conversion dans un registre ?
Hello ;)
Pour comprendre a quoi servent ces deux registres, il faut comprendre le fonctionnement d'un CAN (que je n'expliquerais pas dans un soucis de clareté) donc pour faire precis, la conversion n'est pas instantanée (quelque µs voir ns) Lors de la conversion le convertisseur ne "range" pas la donnée qu'il est en train de calculer directement dans ta variable ( ex : result_conv) Lors de la conversion le resultat est stocké dans un registre temporaire soit ADRESH et ADRESL.
Un registre est contitué de 8bits, alors que notre convertisseur est de 10bits... Et la tu te dira " les registre additioner fond 16bits comment arriver à 10), je te repond "la justification a droite ou a gauche" Pour comprendre je te conseil jde juste d'aller a cette page ( interesse toi qu'au schéma et au text, le code c'est de l'assembleur, et apres les liens je prefere pas cliquer. c'est ici => www.brodeurelectronique.com ( a gauche dans tutoriaux => ADCs)
d'ou le decalage <<8 ;)
je le reconnais j'étais tres rapide la dessus.
AN0=(float)ADRES*q;
Le premier code ne vient pas de moi, je me suis inspiré, donc je supose que ADRES corespond a un registre qui contient directement le resultat selon justification a droite ou a gauche.
Pour exploiter le resultat de ta conversion tu ne peux pas l'utiliser du registre, il faut donc le stocker dans un variable.
Je pense que tu dois savoir, quand tu fais char a=5; a prend la valeur de 5, ici AN0 prend la valeur convertie;)
Apres tu peux en faire de belles choses, par exemple via des if et else if allumer plus ou moins de leds selon le resultats de la conversion, ou encore l'afficher sur un LCD. Ou meme fixer une valeur, avec laquelle tu compares ta conversion qui pourais fermer un Mosfet ou autre... tout est possible ;)
Donc a voir tes questions je suppose que tu as preféré la premiere solution je te la recris sans les // ou /* */
#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;
ADCON0=1;
ADCON1=0x8E;
ADCON0bits.GO_DONE=1;
while(ADCON0bits.GO_DONE)
AN0=(float)ADRES*q;
}
J'ai enlevé la boucle infinie, sinon le programme, resterais toujours dans cette boucle...
Si tu as besoin d'aide pour autre choses ou d'autres precisions ;) demande je pourrais peu etre d'expliquer quelques lignes
bonne programmation
Nico
Pour comprendre a quoi servent ces deux registres, il faut comprendre le fonctionnement d'un CAN (que je n'expliquerais pas dans un soucis de clareté) donc pour faire precis, la conversion n'est pas instantanée (quelque µs voir ns) Lors de la conversion le convertisseur ne "range" pas la donnée qu'il est en train de calculer directement dans ta variable ( ex : result_conv) Lors de la conversion le resultat est stocké dans un registre temporaire soit ADRESH et ADRESL.
Un registre est contitué de 8bits, alors que notre convertisseur est de 10bits... Et la tu te dira " les registre additioner fond 16bits comment arriver à 10), je te repond "la justification a droite ou a gauche" Pour comprendre je te conseil jde juste d'aller a cette page ( interesse toi qu'au schéma et au text, le code c'est de l'assembleur, et apres les liens je prefere pas cliquer. c'est ici => www.brodeurelectronique.com ( a gauche dans tutoriaux => ADCs)
d'ou le decalage <<8 ;)
je le reconnais j'étais tres rapide la dessus.
AN0=(float)ADRES*q;
Le premier code ne vient pas de moi, je me suis inspiré, donc je supose que ADRES corespond a un registre qui contient directement le resultat selon justification a droite ou a gauche.
Pour exploiter le resultat de ta conversion tu ne peux pas l'utiliser du registre, il faut donc le stocker dans un variable.
Je pense que tu dois savoir, quand tu fais char a=5; a prend la valeur de 5, ici AN0 prend la valeur convertie;)
Apres tu peux en faire de belles choses, par exemple via des if et else if allumer plus ou moins de leds selon le resultats de la conversion, ou encore l'afficher sur un LCD. Ou meme fixer une valeur, avec laquelle tu compares ta conversion qui pourais fermer un Mosfet ou autre... tout est possible ;)
Donc a voir tes questions je suppose que tu as preféré la premiere solution je te la recris sans les // ou /* */
#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;
ADCON0=1;
ADCON1=0x8E;
ADCON0bits.GO_DONE=1;
while(ADCON0bits.GO_DONE)
AN0=(float)ADRES*q;
}
J'ai enlevé la boucle infinie, sinon le programme, resterais toujours dans cette boucle...
Si tu as besoin d'aide pour autre choses ou d'autres precisions ;) demande je pourrais peu etre d'expliquer quelques lignes
bonne programmation
Nico
"ADCON1=0x8E;
/* soit 1000 1110; le premier 1 sert a justifier a droite. Le E sert a configurer les pins. */ "
la justification ne se fait pas dans ADCON2 ?
/* soit 1000 1110; le premier 1 sert a justifier a droite. Le E sert a configurer les pins. */ "
la justification ne se fait pas dans ADCON2 ?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Hello,
Tu as de la chance j'ai passé une partie de ma journée dessus je t'ecris un post tout propre dans l'heure ;)
Nico
Tu as de la chance j'ai passé une partie de ma journée dessus je t'ecris un post tout propre dans l'heure ;)
Nico
J'avais pas vu ta reponse,
je te propose de t'y repondre demain ;)
As tu la datasheet du 18f4520 ? ( si non prend sur le site de microchip) il y a souvent beaucoup d'aide. mais tu aura la reponse demain promi
2:40 << tu es un fou de codage xD
Nico
je te propose de t'y repondre demain ;)
As tu la datasheet du 18f4520 ? ( si non prend sur le site de microchip) il y a souvent beaucoup d'aide. mais tu aura la reponse demain promi
2:40 << tu es un fou de codage xD
Nico
Avant d'aller me coucher, je reflechissais;
quand j'utilise le premier code, je me suis apperçu qu'effectivement, il y avait un soucis entre la valeur sur le CAN et la valeur qu'il me donne.
A regarder le code, en effet il y a un soucis, on ne justifie pas ni rien. Donc oui il doit manquer il ligne ;) et donc tu le devine la definition du registre 2, j'y reviendrais dessus demain :)
Veux tu mon Mp sa sera peut etre plus simple ?
Nico
quand j'utilise le premier code, je me suis apperçu qu'effectivement, il y avait un soucis entre la valeur sur le CAN et la valeur qu'il me donne.
A regarder le code, en effet il y a un soucis, on ne justifie pas ni rien. Donc oui il doit manquer il ligne ;) et donc tu le devine la definition du registre 2, j'y reviendrais dessus demain :)
Veux tu mon Mp sa sera peut etre plus simple ?
Nico
Apres multiple test, il y un bien un probleme dans le premier code, on dira qu'il prend les bits aléatoirement, mieux vaut prendre le second ;)
Résolu ?
Résolu ?
Bonjour,
je dois realiser un projet qui consiste a extraire le courant harmonique a travers une charge reliée a un reseau monophasé, puis triphasé. L extraction sera faite de 2 facon, d une a travers un filtre numerique, l otre par un filtre analogique, pour faire la comparaison des 2 resultat. Le filtre analogique comprtera de nbeux can, kon doit realiser a travers le pic16f877, mais mon pb est ke je debute avec le pic et dc je ne c pas comment pgmmer celui ci, en tt k pour la conversion.est ce ke ce st les meme ligne de code ke 18f ?? pourriez vous me donner un petit coup de main pour le code ??merci
je dois realiser un projet qui consiste a extraire le courant harmonique a travers une charge reliée a un reseau monophasé, puis triphasé. L extraction sera faite de 2 facon, d une a travers un filtre numerique, l otre par un filtre analogique, pour faire la comparaison des 2 resultat. Le filtre analogique comprtera de nbeux can, kon doit realiser a travers le pic16f877, mais mon pb est ke je debute avec le pic et dc je ne c pas comment pgmmer celui ci, en tt k pour la conversion.est ce ke ce st les meme ligne de code ke 18f ?? pourriez vous me donner un petit coup de main pour le code ??merci