Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

ADC to simil flottant en C et ASM
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#1 Message par paulfjujo » mar. 25 févr. 2020 11:14

bonjour à tous,

un bout de code oublié (testé en 2017 sur un 18F252, revu pour un 18F26K22)
simple et efficace


char * ADC_To_Float_Str( unsigned char Ch);

N'utilise pas la librairie ADC de MikroE, ni la librarie MATHs et ni du flottant (float sur 32 bits) consommant beaucoup de ressources MCU

Tres proche de l'ASM ! via utilisation des registre
Conversion en ascii pour affichage Simili Flottant ..en ASM
La gamme ADC doit etre 0 à 5V => affichage ascii : 0.010 à 4.990
en entrée : Numero de channel (voie ADC)
en sortie un pointeur sur la chaine de caractere de sortie
donc usage direct possible sur UART,LCD, ....
* Attention : néccessite 10 bytes en zone fixe RAM (absolute adress) pour l'usage de variable en ASM

Nota: le Delay de 22µS est un delay de stabilisation,lorsqu'on change de channel)
Ce déli de 22µs est systematiquement utilisé dans la routine ADC_Read(x) ou ADC_GetSample(x) de la lib ADC MikroE
d'ou les pauvres performenes en terme de NB de KSP/S ( Kilo Samples Per Second)
23.8Ks/sec avec mesure brute 10 bit, stockée en RAM

exemple de resultat sur terminal, avec RA0 à zero, RA1 au +VCC , RA2 curseur potar

Lecture de ADC RA0,RA1,RA2 , Appuyer sur une touche pour sortir ..
0.010 4.996 1.153
0.010 4.996 1.153
0.010 4.996 1.153
0.010 4.996 1.153
0.010 4.996 1.153
0.010 4.996 1.153
0.010 4.996 1.153


code d'essai

Code : Tout sélectionner



//ATTENTION  Variables assignées en Fixe en debut de programme!
  unsigned char CVD00 absolute 0x40;
  unsigned char CVD01 absolute 0x41;
  unsigned char CVD02 absolute 0x42;
  unsigned char Komma absolute 0x43; // virgule ou point decimal
  unsigned char CVD03 absolute 0x44;
  unsigned char CVD04 absolute 0x45;
  unsigned char CVD05 absolute 0x46;
  unsigned char CVD06 absolute 0x47;   // zero terminator de string
  unsigned char ADHIGH absolute 0x48;
  unsigned char ADLOW absolute  0x49;

  unsigned char Channel=0;


 char * ADC_To_Float_Str( unsigned char Ch)
 {
 // la partie ADC doit etre prealablement initialisée
 // voir ADCON0 et ADCON1 ..ou ANSEL
 // n'utilise pas MikroC ADC_Read library  !
 // les 3 instructons ci_dessous peuvent etre oubliées si on gere toujours le meme channel
      ADCON0=Ch<<2; // Selection du channel
      ADCON0.ADON=1;// active le chanel
      Delay_us(22); // delay passe partout , à reduire 
      
      ADCON0
.GO=1; // lance conversion
      _asm Nop    // <- recommandé par Microchip
      while( ADCON0.GO_DONE==1);  // fini
      ADHIGH=ADRESH;
      ADLOW =ADRESL;

  //http://www.piclist.com/techref/A2DCodeGenerator.asp
  //Binary to Decimal converter for 10 Bit A2D
  // 10 bits  5 volts
  // version originale:  ; by : Bill Cornutt   Jan 1, 2006
_asm {
 ; Programme de conversionADC 10 bits  en Ascci decimal
 
; pour rref +VREF=5.00 -VREF=Gnd
 
; les variables   CVD00 à CVD05 contiennet le resultat en caractere ascii
 
;  avec le point ou virgule!decimal   Komma situé entre CVD02 et CVD03
 
;  Fait l'acquisition de l'ADC dans ADHIGH et ADLOW, ensuite lance la conversion CVDEC
 
;  et stocke le resultat dans m CVD00 à CVD05
 
; rev 25/11/2017  paulfjujo
 
;
 ;ATTENTION  Variables  CVD00.. CVD06  à assigner en Fixe en debut de programme!
;
    clear receiving bytes
        CLRF        _CVD00
        CLRF        _CVD01
        CLRF        _CVD02
        CLRF        _CVD03
        CLRF        _CVD04
        CLRF        _CVD05
        CLRF        _CVD06
        movlw 46                  
; separateur=44=Point  ou r  separateur=44 = Virgule
        movwf _Komma         
; separateur decimal
;  for bit 0     2.5
CVDEC00
:
        BTFSS        _ADHIGH,01
        GOTO        CVDEC01
        MOVLW        2          
        ADDWF        _CVD02
,F
        MOVLW        5              
        ADDWF        _CVD03
,F
;  for bit 1     1.25
CVDEC01
:
        BTFSS        _ADHIGH,0
        GOTO        CVDEC02
        MOVLW        1                   
        ADDWF        _CVD02
,F
        MOVLW        2                   
        ADDWF        _CVD03
,F
        MOVLW        5      
        ADDWF        _CVD04
,F
;  for bit 2     0.625
CVDEC02
:
        BTFSS        _ADLOW,07
        GOTO        CVDEC03
        MOVLW        6  
        ADDWF        _CVD03
,F
        MOVLW        2     
        ADDWF        _CVD04
,F
        MOVLW        5    
        ADDWF        _CVD05
,F
;  for bit 3     0.3125
CVDEC03
:
        BTFSS        _ADLOW,6
        GOTO        CVDEC04
        MOVLW        3   
        ADDWF        _CVD03
,F
        MOVLW        1  
        ADDWF        _CVD04
,F
        MOVLW        3   
        ADDWF        _CVD05
,F
;  for bit 4     0.15625
CVDEC04
:
        BTFSS        _ADLOW,5
        GOTO        CVDEC05
        MOVLW        1    
        ADDWF        _CVD03
,F
        MOVLW        5   
        ADDWF        _CVD04
,F
        MOVLW        6   
        ADDWF        _CVD05
,F
;  for bit 5     0.078125
CVDEC05
:
        BTFSS        _ADLOW,4
        GOTO        CVDEC06
        MOVLW        7 
        ADDWF        _CVD04
,F
        MOVLW        8    
        ADDWF        _CVD05
,F
;  for bit 6     0.0390625
CVDEC06
:
        BTFSS        _ADLOW,3
        GOTO        CVDEC07
        MOVLW        3   
        ADDWF        _CVD04
,F
        MOVLW        9   
        ADDWF        _CVD05
,F
;  for bit 7     0.01953125
CVDEC07
:
        BTFSS        _ADLOW,2
        GOTO        CVDEC08
        MOVLW        2   
        ADDWF        _CVD04
,F
;  for bit 8     0.009765625
CVDEC08
:
        BTFSS        _ADLOW,1
        GOTO        CVDEC09
        MOVLW        1   
        ADDWF        _CVD04
,F
;  for bit 9     0.0048828125
CVDEC09
:
        BTFSS        _ADLOW,0
        GOTO        CVDEC10
        MOVLW        5   
        ADDWF        _CVD05
,F
CVDEC10
:
        MOVLW        10   ;D'10'
;   adjust digit  5
CVDEC10a
:
        INCF        _CVD04,F
        SUBWF        _CVD05
,F
        BTFSC        STATUS
,C
        GOTO        CVDEC10a    
;$-3
        
;  went past zero
        DECF        _CVD04
,F
        ADDWF        _CVD05
,F
;   adjust digit  4
CVDEC10b
:
        INCF        _CVD03,F
        SUBWF        _CVD04
,F
        BTFSC        STATUS
,C
        GOTO        CVDEC10b  
; $-3
        
;  went past zero
        DECF        _CVD03
,F
        ADDWF        _CVD04
,F
;   adjust digit  3
CVDEC10c
:
        INCF        _CVD02,F
        SUBWF        _CVD03
,F
        BTFSC        STATUS
,C
        GOTO        CVDEC10c 
; $-3
        
;  went past zero
        DECF        _CVD02
,F
        ADDWF        _CVD03
,F
;   adjust digit  2
 CVDEC10d
:
        INCF        _CVD01,F
        SUBWF        _CVD02
,F
        BTFSC        STATUS
,C
        GOTO         CVDEC10d 
;GOTO        $-3
        
;  went past zero
        DECF        _CVD01
,F
        ADDWF        _CVD02
,F
;   adjust digit  1
 CVDEC10e
:
        INCF        _CVD00,F
        SUBWF        _CVD01
,F
        BTFSC        STATUS
,C
        GOTO        CVDEC10e 
; $-3
        
;  went past zero
        DECF        _CVD00
,F
        ADDWF        _CVD01
,F
        
;  no need to adjust high order byte
;   convert to ascii
        MOVLW        48           
;D'48'
        ADDWF        _CVD00,F   //centaine
        ADDWF        _CVD01,F   // dizaines
        ADDWF        _CVD02,F   //unites
        ADDWF        _CVD03,F   // 1/10e
        ADDWF        _CVD04,F   // 1/100e
        ADDWF        _CVD05,F   // 1/1000e
//        variante avec un blanc devant les unites
        MOVLW 32
        MOVWF _CVD00
,F
        MOVWF _CVD01
,F
 
;        max value ADC  is 4.996
 
;         min value ADC is 0.010
 
;        RETURN
 
} //asm
 return &CVD00 ;
 // return &CVD02;     // saute par dessus les 2 zeros ou blancs inutiles
}

=====================
utilisation :
======================
#define CLS 12
#define CR 13
#define LF 10
#define TAB 9
#define BACK 8
 #define Directory  "C:\\_MikroC\\_MesProjets_MikroC\\_18F26K22_46K22 "
 #define Project   "18F26k22_UART1_RX_IT_ADC0_Base.mcppi"
 #define Source     "_18F26K22_16Mhz_Uart1_Base_"
 #define HARDWARE  "Carte Base 18F26K22  ou 18F en 28 Pins"
 #define FOSC_INTERNE
 #define FOSC "64MHz"
 #define MCU  "18F26K22"
 #define POWER_Supply "3.0 to 5.0V"

unsigned char TEXTE[128];
unsigned char * txt;
int i,j,k;

void Print(const char * q)
{
 while(*q)
 {
  UART1_Write(*q++);
 }
}
 

void CRLF1
()
{
  UART1_Write(CR);
  UART1_Write(LF);
 }
 
void main
() 
{
 #ifdef FOSC_INTERNE
 //OSCCON = 0b01110010  ; //0x72 ;     //Oscillateur à 16Mhz
 //OSCTUNE.PLLEN=0;
 OSCTUNE=0;
 OSCCON = 0b01110000  ; //0x70 ;     //Oscillateur à 16Mhz + PLL
 OSCTUNE.PLLEN=1;
 while (OSCCON.HFIOFS==0); // wait stable oscillator
 #else
 // Q=20Mhz
 #endif

DataReady1=0;
CptFO1=CptFE1=0;
txt=TEXTE;


UART1_Init(19200);  // Initalize USART (38400,8,N,1)
UART_Set_Active(&UART1_Read, &UART1_Write, &UART1_Data_Ready, &UART1_Tx_Idle);
clk = Clock_kHz();
sprintf(txt," Clock initiale  = %05u KHz\r\n",clk);
UART1_Write_Text(txt); 

 Channel
=0;
 TRISA=0xFF;
 ANSELA.ANSA0=1;
 ANSELA.ANSA1=1;
 ANSELA.ANSA2=1;
// init module ADC
 ADCON1=0;  // +Vref=+VDD  et -VREF=Gnd
 //   ADCON2  Register 17-3 page 306
 //    ADFM —  ACQT<2:0> ADCS<2:0>
 //    1   0   110       101
 ADCON2=0b10110101;  // right ustied  16TAD  FOSC/16
do
{
  do
  
{
    Print(" Lecture de ADC RA0,RA1,RA2 , Appuyer sur une touche pour sortir .. \r\n");
      do
      
{
       Channel=0; UART1_Write_Text( ADC_To_Float_Str(Channel)); UART1_Write(TAB);
       Channel=1; UART1_Write_Text( ADC_To_Float_Str(1)); UART1_Write(TAB);
       Channel=2;  UART1_Write_Text( ADC_To_Float_Str(2)); UART1_Write(TAB);
        CRLF1();
       Delay_1sec();
       }
      // test en pooling sans gestion interruption
    while(UART1_Data_Ready()==0) ;
    CRLF1();
  } while(1);
 }

Aide toi, le ciel ou FantasPic t'aidera

Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 50 invités