Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] ADC without using MikroC libraries

Status
Not open for further replies.

shubham kumar

Member level 3
Member level 3
Joined
Sep 11, 2014
Messages
59
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Location
bangalore
Visit site
Activity points
511
Hi I am trying to implement the ADC without using the library functions like ADC_init() and ADC_Read().
I followed the data-sheet for the same but didn't got through.

I am using PIC18F452 at a frequency of 20MHz. // (which will be 20/4=5Mhz later)

Here is my code.
Code:
void AD_init();
int AD_Read(unsigned char ); 

void main()
{
int i;
unsigned char txt[16];
LCD_init();
 
AD_init();

 while(1){
     i=AD_Read(1);

IntToStr(i,txt);
 
    LCD_out(1,1,txt);
    LCD_out(2,8,"mikroC");
      }
}

 void AD_init()
  {
  ADCON1=0x04;             // AN0,AN1,AN3 = analog pins rest as digital
  }

  int AD_Read(unsigned char pt)       //here I am just taking the channel but  not using it
  {                                             // late I'll try to make it concatenate in ADCON0 for any channel
  int k;

   k= (0x01001000 ) ;   //channel selection as 1 and clock selection as T/8
   ADCON0 = k;

   ADCON0.B0=1;                            //ADC powered on
   ADCON0.B2 = 1;   Delay_ms(10);    //conversion start
   while( ADCON0.B2==1);                 // wait till conversion
   k=ADRESH;
   return (k);
  }
 

I don't get it. You are using MikroC and do not want to use MikroC libraries.
Switch yourself to assembler (MPLAB, MPLABX) that way you will have to write your own functions and will not be tied to any compiler, besides MPASM.
Or better, write your own assembler :D
 

hello

Here is an example of using ADC 100% asm

you can use _asm directive in mikroC to use it
or use C to initilalise the register ?


Code:
;  INITIALIZE PART

;------------------------------------------
; Configuration Voie ANALOGIQUE et logiques
;right justified, max.ref = sur RA3 pin4 et min.ref= sur RA2 pin 3
; voie analogique AN0 pin RA0  sur Pin 2
; voie analogique AN1 pin RA1  sur Pin 3
; voie analogique AN4 pin RA5  sur pin 7
; RA4=Digital sur Pin 6
;-------------------------------------------
       movlw b'10001011' ; RA0,RA1,RA2,RA5= ANA, RA3=+Vref,  RE0..RE2=digital ,cadre a droite
    movwf ADCON1    ; 1100    D D D A VREF+ VREF- A A
    movlw b'00101111' ; RA0,RA1,RA2,RA3,RA5 en entrees car ANA , RA4 en sorie Digit output
    movwf TRISA


;------------------------------------------
;bit 7-6: ADCS1:ADCS0: A/D Conversion Clock Select bits  10 = FOSC/32
;bit 5-3: CHS2:CHS0: Analog Channel Select bits          000 = channel 0, (RA2/AN2) RA0,1,2,3,5
;bit 2: GO/DONE: A/D Conversion Status bit,If ADON = 1   1=in progress  0=Done
;bit 1: Unimplemented:                                   Read as '0'
;bit 0: ADON: A/D On bit                                 1 = A/D converter module is operating
    movlw b'10000001'   ;clock/32  Channel=0 ADON=1
    movwf ADCON0
    
       
; USE INSIDE YOUR MAIN PROGRAM    

    movlw 0x81                ;ana0
    movwf Voie
    call Acquis_Ana
    call delay_10mS    

    movlw 0x89                ; ana1
    movwf Voie
    call Acquis_Ana    
    call delay_10mS    
    
    movlw 0xA1                ; ana4
    movwf Voie
    call Acquis_Ana    
    call delay_10mS
    
    CALL Rs_CrLf
 
    
    
    
;**************** 
;Subroutines 
;**************** 
Acquis_Ana             ;armemement acquisition Analogique
    movf Voie,w,0
    movwf ADCON0
    bsf ADCON0,ADON     ; set Analog Converter ON (ADCON0,0=1)
    call delay_50uS
    bsf ADCON0,GO_DONE  ; set GO on start conversion (ADCON0,2=1)
    call delay_50uS
    bcf RETENUE        ; Positif
not_yet
    btfsc ADCON0,NOT_DONE  ; conversion AD ok ?(ADCON0,2=0 ???)
    goto not_yet
    movf ADRESL,w
    movwf val1,1
    movwf val3,1
    movf ADRESH,w
    movwf val1+1,1
    movwf val3+1,1         
Posit1
    bcf Drapeaux,5,0  ; mode XXXXX
    bcf RETENUE
    call bcd_temp   ; remplit le buffer d'affichage ASCII
    movlw TABUL
    call Rs_Putchar
    return


;---------------- Binary (16-bit) to BCD -----------------------
; 16-bit-Binary  ->  4 digits de 8bits
; ( val1:val1+1) ->  Dixmil , mille , cent , dix , uno 
bcd_temp 
        swapf   val1+1,W,1     ; HIGH
        andlw   0x0F
        addlw   0xF0
        movwf   mille,1 
        addwf   mille,F,1 
        addlw   0xE2 
        movwf   cent,1 
        addlw   0x32 
        movwf   uno,1 
        movf    val1+1,W,1 
        andlw   0x0F 
        addwf   cent,F,1 
        addwf   cent,F,1 
        addwf   uno,F,1 
        addlw   0xE9 
        movwf   dix,1 
        addwf   dix,F,1 
        addwf   dix,F,1 
        swapf   val1,W,1         ; LOW
        andlw   0x0F 
        addwf   dix,F,1 
        addwf   uno,F,1 
        rlcf     dix,F,1 
        rlcf     uno,F,1 
        comf    uno,F,1 
        rlcf     uno,F,1 
        movf    val1,W,1 
        andlw   0x0F 
        addwf   uno,F,1 
        rlcf     mille,F,1 
        movlw   0x07 
        movwf   dixmil,1
        movlw   0x0A             
Lb1: 
        decf    dix,F,1 
        addwf   uno,F,1 
        btfss   STATUS,C 
        bra   Lb1 
Lb2: 
        decf    cent,F,1 
        addwf   dix,F,1 
        btfss   STATUS,C 
        bra   Lb2 
Lb3: 
        decf    mille,F,1 
        addwf   cent,F,1 
        btfss   STATUS,C
        bra   Lb3 
Lb4: 
        decf    dixmil,F,1 
        addwf   mille,F ,1
        btfss   STATUS,C 
        bra   Lb4 

    btfss Drapeaux,5    ; 1 => affichage 00000 a 999999
    bra  Bcd_5digits   ; 0 => affichage + ou - XXX.XX

    movlw '+'
    btfsc RETENUE,0
    movlw '-'
    call Rs_Putchar

    movf   mille,w,1
    btfss STATUS,Z     ; si digit=0 remplace par Blanc
    bra Lb5

    movlw ' '
    call Rs_Putchar
    bra Lb6
Lb5  
    addlw  '0'
    call Rs_Putchar
Lb6
    movf   cent,w,1
    addlw  '0'
    call Rs_Putchar
    movlw '.'
    call Rs_Putchar
    movf   dix,w,1
    addlw  '0'
    call Rs_Putchar
    movf   uno,w,1
    addlw  '0'
    call Rs_Putchar
    return

;---------------
Bcd_5digits
;    movf   dixmil,w
;    addlw  '0'
;    call Rs_Putchar
;    bank1
    movf   mille,w,1
    addlw  '0'
    call Rs_Putchar
    movf   cent,w,1
    addlw  '0'
    call Rs_Putchar
    movf   dix,w,1
    addlw  '0'
    call Rs_Putchar 
    movf   uno,w,1
    addlw  '0'
    call Rs_Putchar
    movlw    ' '
    call Rs_Putchar
       return


i joined the complete asm code ..
 

Attachments

  • 18F252_3ANA_IR_rs232_091128_ok.asm.txt
    44.4 KB · Views: 95
@milan.rajik,
I thought that first I'll get the value of ADRESH, then I'll concatenate it with the ADRESL. but that too I am not getting.

@ZASto
I am not very good at programming, so I thought that instead of using built functions if I'll do their coding then it would be better for me, while making some functions like (IntToStr), I learned how to use pointers in a function. If someone writes code in other software and if I don't know the basic then how am I going to help.
 
Last edited:

First try doing small projects using built-in mikroC libraries. Later you can make your own libraries. The PIC (your device) datasheet ADC section mentions the steps in adc conversion. Some PIC datasheets even give sample asm code for adc. Convert asm code to c code. To get better help post your circuit and also Zip and post complete mikroC project files.


Code C - [expand]
1
while( ADCON0.B2==1);



ADCON0.B2 is not GO/DONE bit. GO/DONE bit is ADCON0.B1 (Bit counting starts from .B0 to .B7)
 

thanks,

In the same code if I replace my function /AD_Read()/ by inbuilt function /ADC_Read()/ then this program is running superbly. :) .
Second is, ADCON0.B2 is GO/DONE bit, B1 is unimplemented, and B0 is ADON bit (you might be telling with reference to any other controller, I am using PIC18F452).

I'll be posting the zip files, after trying a few more times. :)
 

Hi, I did it.
I am getting 870 instead of 1023 for full +5 volts. this is because I havn't concatenated ADRESL with ADRESH.

But the thing which is confusing is how to use ADRESL and ADRESH, since both are 8 bit registers and ADC has 10 bit resolution that means some bits of both registers would be overlapping. So, how would I concatenate them. (I can try permutation combination but which one is correct).

like should I take 8 bits of ADRESH and (take lower two bits of ADRESL or higher two bits of ADRESL)
or take the other way like 2MSB of ADRESH and rest from ADRESL

++

what does this means
ADFM: A/D Result Format Select bit
1 = Right justified. Six (6) Most Significant bits of ADRESH are read as ’0’.
0 = Left justified. Six (6) Least Significant bits of ADRESL are read as ’0’.

(in the program I am using right justified but didnt understood that if 6MSB are cleared then how I'll get the correct value.)
Please clarify me on this.
 

If ADFM is set to 1 then you will have right justified 10 bit result like 00000011 11111111 = 1023. If ADFM is cleared (0) then it will be left justified result 11111111 11000000. Use ADFM = 1.


Code C - [expand]
1
2
unsigned int adc_result = 0;
adc_result = (ADRESH << 8) | ADRESL;

 

Firstly understand that you can't hold a 10 bit value in an 8 bit register, you have to treat it as a high part in one 8-bit variable and a low part on another 8-bit variable. 18F assembly language doesn't understand constructs like 'integer' and 'float', the only type of variable it knows is equivalent to 'unsigned char', in other words simply eight binary bits.

To use the ADC, follow these steps:
1. turn the ADC module on. No need to turn it off if you are taking more measurments.
2. load the control registers to select the channel you want and a suitable conversion time
3. ONLY at this point, add a delay to allow the voltage to settle through the PIC's amplifier and sample/hold circuits
4. set the GO/-DONE bit to start the conversion.
5. wait for the bit to indicate the conversion is finished. Don't add your own delay, just wait for the ADC to tell you it is ready.
6. read the ADRESH and ADRESL registers to get your value.

ADFM sets how the 10-bit result is presented within the 16 bits width of both the ADRESH and ADRESL register pair. It is entirely up to you how you choose to use the result, the significant digits are the same, the only difference is whether the result is aligned to the left or right side of the 16 bit representation. For simplicity, I suggest you use right justification so the uppermost bits are all zero and the lowermost bits can be read as the value directly.

Brian.
 
Thanks a lot. @Brian, @milan.rajik
I tried to understand with the data sheet, it wasn't clear but after reading your post it looks like it was nothing.
Now, I got it. Thanks.


-----
Shubham

In search of another problem :)
 

To explain why the two formats are so useful.

Right justified returns the 10-bit value in directly usable format.
Left justified allows you to ignore the ADRESL completely and gives 8-bit ADC resolution by reading only the ADRESH register. This is useful if you only need lower resolution.

Brian.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top