Bonjour à tous,
J'ai commencé depuis quelques temps la programmation de pic32 avec le compilateur XC32.
Dans le cadre d'un projet, j'utilise un PIC32MX270F512H où j'aimerais scanner 21 entrées analogiques. Ce PIC ne peut scanner que 16 entrées en une fois, donc je fais ça en deux fois en jouant sur le registre AD1CSSL : la première fois je scanne mes 16 premières entrées, puis la seconde fois, je scanne les 5 autres.
Ca marche presque...J'ai toujours une entrée qui me renvoie n'importe quoi. Une valeur à peu près fixe (entre 45 et 150) d'une conversion à l'autre, mais qui est fausse. Je suis sensé lire 0, comme sur les autres entrées. C'est certainement un problème logiciel car si je change le nombre d'entrée à scanner, j'ai toujours le même problème sur une autre broche. Quand j'applique des signaux sur les entrées, ils donnent tous la bonne valeur, sauf la pin à problème.
J'ai vérifié à l'oscillo que tout se passait bien sur mes entrées, et rien de spécial à signaler, j'ai une petite de dizaines de mV d'amplitude de bruit avec l'adc actif.
Sur chaque entrée, j'ai branché la sortie d'un même pont diviseur, avec un condo de 100n. L'ADC voit une impédance d'environ 1k (< 5k de la doc)
Voici le code de configuration de l'adc :
Code:void ADC_Init(struct APP_DATA* appData){ mAppData = appData; AD1CON1bits.ON = 0; //turn off adc ANSELB = 0xFFFF; TRISB = 0xFFFF; AD1CHSbits.CH0NA = 0; // Mux A negative input from VR- AD1CHSbits.CH0SA = 0; AD1CON1bits.FORM = 4; //32bits output format AD1CON1bits.SSRC = 0b111; //auto convert trigger AD1CON1bits.CLRASAM = 0; //buffer contents will be overwritten by the next conversion sequence AD1CON2bits.VCFG = 0; //voltage reference from Vss to Vdd AD1CON2bits.CSCNA = 1; //scan input enabled AD1CON2bits.SMPI = NBR_SAMPLE_MEASURES1-1; //sample per interrupt AD1CON2bits.BUFM = 0; //16bit buffer AD1CON2bits.ALTS = 0; //mux A only AD1CON3bits.ADRC = 0; //Pbclock selected AD1CON3bits.ADCS = 9; //Tad AD1CON3bits.SAMC = 31; //auto sample time AD1CSSL = 0; AD1CSSL = 0xFFFC; //on sélectionne les entrées de A2 à A15 AD1CSSLbits.CSSL18 = 1; AD1CSSLbits.CSSL19 = 1; //analog input never used /*AD1CSSLbits.CSSL0 = 0; AD1CSSLbits.CSSL1 = 0; AD1CSSLbits.CSSL21 = 0; AD1CSSLbits.CSSL22 = 0; AD1CSSLbits.CSSL24 = 0; AD1CSSLbits.CSSL25 = 0; AD1CSSLbits.CSSL26 = 0;*/ AD1CON1bits.ON = 1; IFS0bits.AD1IF = 0; //clear adc interrupt flag AD1CON1bits.ASAM = 1; //ADC Sample Auto-Start bit }
J'appelle la fonction suivante toutes les 10ms, pour lire les buffers de l'ADC :
Voyez-vous un problème dans ce code ?Code:void ADC_ReadData(){ if(IFS0bits.AD1IF == 0) return; AD1CON1bits.ASAM = 0; //stop auto sample AD1CON1bits.ON = 0; //stop adc MeasuresAdc *measures = NULL; ANSELB = 0xFFFF; TRISB = 0xFFFF; //on ne peut scanner que 16 entrées en une fois. Donc une fois sur deux, on change les canaux à scanner grâce au flag ci-dessous if(flagSwitchAdcChannels) { flagSwitchAdcChannels = false; measures = &mAppData->measuresAdc1; //on stock les résultats là-dedans uint8_t i = 0; for(i = 0; i < NBR_SAMPLE_MEASURES1; i++){ measures->tabMeasures[i] = DRV_ADC_SamplesRead(i); //read adc buffers } //select analog inputs for next conversion AD1CSSL = 0; AD1CSSLbits.CSSL16 = 1; AD1CSSLbits.CSSL17 = 1; AD1CSSLbits.CSSL20 = 1; AD1CSSLbits.CSSL23 = 1; AD1CSSLbits.CSSL27 = 1; AD1CON2bits.SMPI = NBR_SAMPLE_MEASURES2-1; } else { flagSwitchAdcChannels = true; measures = &mAppData->measuresAdc2; uint8_t i= 0; for(i = 0; i < NBR_SAMPLE_MEASURES2; i++){ measures->tabMeasures[i] = DRV_ADC_SamplesRead(i); //read adc buffer } AD1CSSL = 0; AD1CSSL = 0xFFFC; //select A2 throught A15, A18 and A19 for scan AD1CSSLbits.CSSL18 = 1; AD1CSSLbits.CSSL19 = 1; AD1CON2bits.SMPI = NBR_SAMPLE_MEASURES1-1; mAppData->errors.firstAdcConversionDone = 1; } IFS0bits.AD1IF = 0; //clear adc interrupt flag AD1CON1bits.ON = 1; //turn adc on AD1CON1bits.ASAM = 1; //start auto sample }
En espérant n'avoir rien oublié
Merci beaucoup pour votre aide !
-----