/******************************************************** /* Mise en ouvre du can du 16F877 * /* * /* En utilisant la carte demo icd (OSC rc à 4 Mhz ) * /* on sort sur le port C la valeur retournée par la * /* conversion de la tension sur RA0 * /* on utilise seulement les 8 bits de poids forts du * /* résultat sur 10 bits et donc on justifie le résultat * /* à gauche et on utilise ADRESH * /* * /* Auteur : Arlotto Date : 08/01/03 * /* * /* * /********************************************************/ #include void InitCan(void); unsigned char ReadCan8bit(unsigned char ch); void waitRAT(void); void main(void) { InitCan(); TRISC = 0 ; while(1) { PORTC = ReadCan8bit(0); } } void InitCan(void) { ADCON1 = 0x02 ; /*Port E digital , Port A analogique , justification gauche*/ ADCON0 = 0x41 ; /*Tad = 8*Tosc = 8 * 0.25µs = 2µs > 1.6µs , ADON ;*/ ADIF = 0 ; } unsigned char ReadCan8bit(unsigned char ch) { ADCON0 &= 0xC7 ; /* RAZ CHSx */ /* Sélection du canal */ if ( ch & 1 ) { CHS0 = 1 ; } if ( ch & 2 ) { CHS1 = 1 ; } if ( ch & 4 ) { CHS2 = 1 ; } waitRAT(); /* Attendre le temps d'acquisition */ ADGO = 1 ; /* Démarre la conversion */ /* Attend la fin de conversion */ while (ADGO && ADON) /* Par sécurité on teste aussi ADON */ ; /* car sinon on rentre dans une boucle infinie */ return ADRESH ; } /******************************************************************************************** * Required acquisition time for A/D module form Max. Heise 2002 * p. 115 equation 11-1 Tacq=19,72,e-6 * seconds, approx. 2,e-5 seconds. * One instruction is executed in one * cycle, one cycle at 4MHz takes 2,5,e-7 * seconds. Thus we must idle for 80 * instructions * Formula for this loop * Inst(I)=1+1+( (I-1)*(1+2) )+2+2=6+3I-3=3I+3 * +2 Inst.Cycles for the call of this function * => Inst(I)=3I+5 * Inst(I) must be 80 * 80=3I+5 * => I=25 * Timing critical, so this is still in assembler. ********************************************************************************************/ char counter ; void waitRAT(void) { #asm I EQU 50 ; Note this is actually twice the required value of I, just to be sure movlw I ; 1 Inst.Cycle movwf _counter ; 1 Inst.Cycle WaitRAT_Loop decfsz _counter,f ; 1 Inst.Cycle if I!=0, 2 Inst.Cycles if I==0 goto WaitRAT_Loop ; 2 Inst.Cycles #endasm }