configuring analog and digital pins

Thread Starter

abo zaynab

Joined May 1, 2018
35
im trying to configure one analog pin in port a im using pic 16f877a ,the other pins i want to use them as digital input but once im turning on adc module,other pins doesnt work correctly idk why
here is a piece of my code;
trisa=0x3f;
ADCON0=0b11000001;
ADCON1=0b11001110;
even if tried
adc_init();
the same result
wlevel=adc_read(0);
im using mikroc
 

JohnInTX

Joined Jun 26, 2012
4,787
adc_init() is not in my version of MikroC so I don't know anything about it. With your other code, the ADC should work without it.

I don't see anything wrong with your initialization:
One channel (AN0)
Other pins on PORTA are digital inputs.
ADC clock is the internal RC oscillator
When you call adc_read() it should return an analog value.

the other pins i want to use them as digital input but once im turning on adc module,other pins doesnt work correctly idk why
Do the other pins work correctly before enabling the ADC?
How are they failing after enabling the ADC?
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
adc_init() is not in my version of MikroC so I don't know anything about it. With your other code, the ADC should work without it.

I don't see anything wrong with your initialization:
One channel (AN0)
Other pins on PORTA are digital inputs.
ADC clock is the internal RC oscillator
When you call adc_read() it should return an analog value.


Do the other pins work correctly before enabling the ADC?
How are they failing after enabling the ADC?
Without turning on the ADC module the digital pins just works fine as input and output but after initializing the ADC module it's just working as floating or idk how to describe it just it doesn't work as I wanted for example if I'm initializing any pin except ra4 because isnt analog pin as input and im connecting pullup resistor to it ,it works as if I'm pushing the button to ground
 

JohnInTX

Joined Jun 26, 2012
4,787
for example if I'm initializing any pin except ra4 because isnt analog pin as input and im connecting pullup resistor to it ,it works as if I'm pushing the button to ground
Pins configured as analog but read as digital pins will indeed read '0'. From the information you provided above, the pin should read as a digital pin.
If you post your code, preferably something that will compile, I can take a look at it. Otherwise, you can inspect the operation in the simulator. Set a breakpoint after initializing the IO and verify that the registers are set up correctly then run to a point after the ADC operation and see if anything has changed.
Also, review the simple stuff like the PIC configuration, correct PIC type etc.
Are you running this on actual hardware?
 

trebla

Joined Jun 29, 2019
542
adc_init() is not in my version of MikroC so I don't know anything about it
This function exist in my version of MikroC, unfortunately i can't test it because MikroC throws weird errors and refuses compile and manage files. And it does this on both of my PCs. dsPIC and PIC32 versions work correctly.

ADCON1=0b11001110; - according to datasheet 6th bit does nothing in this register. But i think this is not the reason of TS project problems.
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
This function exist in my version of MikroC, unfortunately i can't test it because MikroC throws weird errors and refuses compile and manage files. And it does this on both of my PCs. dsPIC and PIC32 versions work correctly.

ADCON1=0b11001110; - according to datasheet 6th bit does nothing in this register. But i think this is not the reason of TS project problems.
Adcon1 according to datasheet choose the analog pins 1110 means ra1as analog the rest as digital
 

JohnInTX

Joined Jun 26, 2012
4,787
The listing in the .rar implies that adc_init() is setting all of the pins to ANALOG:
Excerpt from main_code.lst file:
;__Lib_ADC_A_C.c,0 :: ?ICS_vref_mask
0x00FE    0x340F ;?ICS_vref_mask+0  ; RETLW 0fh (_vref_mask = 0fh). Copied into RAM at 2ch  <<<<<<------
; end of ?ICS_vref_mask

_ADC_Init:
;__Lib_ADC_A_C.c,19 ::   
;__Lib_ADC_A_C.c,20 ::   
0x0039    0x30FF          MOVLW      _ADC_Get_Sample
0x003A    0x1283          BCF        STATUS, 5
0x003B    0x1303          BCF        STATUS, 6
0x003C    0x00C0          MOVWF      _ADC_Get_Sample_Ptr
0x003D    0x30FF          MOVLW      hi_addr(_ADC_Get_Sample)
0x003E    0x00C1          MOVWF      _ADC_Get_Sample_Ptr+1
0x003F    0x30FF          MOVLW      FARG_ADC_Get_Sample_channel
0x0040    0x00C2          MOVWF      _ADC_Get_Sample_Ptr+2
0x0041    0x30FF          MOVLW      hi_addr(FARG_ADC_Get_Sample_channel)
;__Lib_ADC_A_C.c,22 ::   
0x0042    0x019F          CLRF       ADCON0
;__Lib_ADC_A_C.c,23 ::   
0x0043    0x30C0          MOVLW      192
0x0044    0x049F          IORWF      ADCON0, 1
;__Lib_ADC_A_C.c,24 ::   
0x0045    0x092C          COMF       _vref_mask, 0  ; W = F0h <<<<---- read to W from 2ch in RAM
0x0046    0x00F0          MOVWF      R0
0x0047    0x0870          MOVF       R0, 0
0x0048    0x1683          BSF        STATUS, 5
0x0049    0x059F          ANDWF      ADCON1, 1      ;<<<<——- clears lower 4 bits of ADCON1, making all inputs ANALOG <<<-----
;__Lib_ADC_A_C.c,25 ::   
0x004A    0x171F          BSF        ADCON1, 6      ; clock spec
;__Lib_ADC_A_C.c,26 ::   
0x004B    0x179F          BSF        ADCON1, 7      ; left-justified
;__Lib_ADC_A_C.c,29 ::   
0x004C    0x1283          BCF        STATUS, 5
0x004D    0x141F          BSF        ADCON0, 0
;__Lib_ADC_A_C.c,30 ::   
L_end_ADC_Init:
0x004E    0x0008          RETURN
; end of _ADC_Init
I don't know why but it looks like the code generated by adc_init() is resetting all ADC inputs to ANALOG. It would explain why calling adc_init() causes the other PORTA pins to be read as '0' (they are analog pins again). A brief scan of the rest of the generated code shows the same clearing of PCFG<3:0> in ADCON1 every time it is accessed, as far as I can see.

As I noted earlier, to test this run the code and inspect your ADCON1 value before and after adc_init(). If the problem is confirmed and there are no project options to specify digital vs. analog pins you may have to run the ADC without the 'benefit' of the library routines.

Does your version of MikroC have a separate configuration utility for the ADC that controls how the code is compiled?

That's the best I have so far.
 
Last edited:

trebla

Joined Jun 29, 2019
542
There is ADC_Init_Advanced() function but it has little use in this case because it deals mostly with voltage references. I think TS should avoid using ADC_Init and set ADC configurations by registers.
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
The listing in the .rar implies that adc_init() is setting all of the pins to ANALOG:
Excerpt from main_code.lst file:
;__Lib_ADC_A_C.c,0 :: ?ICS_vref_mask
0x00FE    0x340F ;?ICS_vref_mask+0  ; RETLW 0fh (_vref_mask = 0fh). Copied into RAM at 2ch  <<<<<<------
; end of ?ICS_vref_mask

_ADC_Init:
;__Lib_ADC_A_C.c,19 ::  
;__Lib_ADC_A_C.c,20 ::  
0x0039    0x30FF          MOVLW      _ADC_Get_Sample
0x003A    0x1283          BCF        STATUS, 5
0x003B    0x1303          BCF        STATUS, 6
0x003C    0x00C0          MOVWF      _ADC_Get_Sample_Ptr
0x003D    0x30FF          MOVLW      hi_addr(_ADC_Get_Sample)
0x003E    0x00C1          MOVWF      _ADC_Get_Sample_Ptr+1
0x003F    0x30FF          MOVLW      FARG_ADC_Get_Sample_channel
0x0040    0x00C2          MOVWF      _ADC_Get_Sample_Ptr+2
0x0041    0x30FF          MOVLW      hi_addr(FARG_ADC_Get_Sample_channel)
;__Lib_ADC_A_C.c,22 ::  
0x0042    0x019F          CLRF       ADCON0
;__Lib_ADC_A_C.c,23 ::  
0x0043    0x30C0          MOVLW      192
0x0044    0x049F          IORWF      ADCON0, 1
;__Lib_ADC_A_C.c,24 ::  
0x0045    0x092C          COMF       _vref_mask, 0  ; W = F0h <<<<---- read to W from 2ch in RAM
0x0046    0x00F0          MOVWF      R0
0x0047    0x0870          MOVF       R0, 0
0x0048    0x1683          BSF        STATUS, 5
0x0049    0x059F          ANDWF      ADCON1, 1      ;<<<<——- clears lower 4 bits of ADCON1, making all inputs ANALOG <<<-----
;__Lib_ADC_A_C.c,25 ::  
0x004A    0x171F          BSF        ADCON1, 6      ; clock spec
;__Lib_ADC_A_C.c,26 ::  
0x004B    0x179F          BSF        ADCON1, 7      ; left-justified
;__Lib_ADC_A_C.c,29 ::  
0x004C    0x1283          BCF        STATUS, 5
0x004D    0x141F          BSF        ADCON0, 0
;__Lib_ADC_A_C.c,30 ::  
L_end_ADC_Init:
0x004E    0x0008          RETURN
; end of _ADC_Init
I don't know why but it looks like the code generated by adc_init() is resetting all ADC inputs to ANALOG. It would explain why calling adc_init() causes the other PORTA pins to be read as '0' (they are analog pins again). A brief scan of the rest of the generated code shows the same clearing of PCFG<3:0> in ADCON1 every time it is accessed, as far as I can see.

As I noted earlier, to test this run the code and inspect your ADCON1 value before and after adc_init(). If the problem is confirmed and there are no project options to specify digital vs. analog pins you may have to run the ADC without the 'benefit' of the library routines.

Does your version of MikroC have a separate configuration utility for the ADC that controls how the code is compiled?

That's the best I have so far.
I dkn what u mean by how the code is compiled ? . I just when I finish the code press on compile button that's it
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
There is ADC_Init_Advanced() function but it has little use in this case because it deals mostly with voltage references. I think TS should avoid using ADC_Init and set ADC configurations by registers.
I ve set ADC also by registers also the same once I use ADC init() or ADCon bit=1 I feel like ADC module once it's powered on it's attached to all analoge pins even in port e if it's configured as digital input
 

trebla

Joined Jun 29, 2019
542
Unfortunately, MikroC libraries are pre-compiled and not documented well so i don't know what exactly ADC_Init() function does but seems that it sets all available pins to analog mode. If you want use only one analog pin then do not use this particular function.
You only need these lines you already have in your code:

trisa=0x3f;
ADCON0=0b11000001;
ADCON1=0b10001110; // corrected according to post #8

Maybe this will also work if you call ADC_Init() function before you set ADCON1 register as it will override ADC_Init() pin settings.
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
Unfortunately, MikroC libraries are pre-compiled and not documented well so i don't know what exactly ADC_Init() function does but seems that it sets all available pins to analog mode. If you want use only one analog pin then do not use this particular function.
You only need these lines you already have in your code:

trisa=0x3f;
ADCON0=0b11000001;
ADCON1=0b10001110; // corrected according to post #8

Maybe this will also work if you call ADC_Init() function before you set ADCON1 register as it will override ADC_Init() pin settings.
REGISTER 11-1: ADCON0 REGISTER (ADDRESS 1Fh)
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 U-0 R/W-0
ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE — ADON
bit 7 bit 0
bit 7-6 ADCS1:ADCS0: A/D Conversion Clock Select bits (ADCON0 bits in bold)
bit 5-3 CHS2:CHS0: Analog Channel Select bits
000 = Channel 0 (AN0)
001 = Channel 1 (AN1)
010 = Channel 2 (AN2)
011 = Channel 3 (AN3)
100 = Channel 4 (AN4)
101 = Channel 5 (AN5)
110 = Channel 6 (AN6)
111 = Channel 7 (AN7)
Note: The PIC16F873A/876A devices only implement A/D channels 0 through 4; the
unimplemented selections are reserved. Do not select any unimplemented
channels with these devices.
bit 2 GO/DONE: A/D Conversion Status bit
When ADON = 1:
1 = A/D conversion in progress (setting this bit starts the A/D conversion which is automatically
cleared by hardware when the A/D conversion is complete)
0 = A/D conversion not in progress
bit 1 Unimplemented: Read as ‘0’
bit 0 ADON: A/D On bit
1 = A/D converter module is powered up
0 = A/D converter module is shut-off and consumes no operating current

REGISTER 11-2: ADCON1 REGISTER (ADDRESS 9Fh)
R/W-0 R/W-0 U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0
ADFM ADCS2 — — PCFG3 PCFG2 PCFG1 PCFG0
bit 7 bit 0
bit 7 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’.
bit 6 ADCS2: A/D Conversion Clock Select bit (ADCON1 bits in shaded area and in bold)
bit 5-4 Unimplemented: Read as ‘0’
bit 3-0 PCFG3 CFG0: A/D Port Configuration Control bits
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
- n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Note: On any device Reset, the port pins that are multiplexed with analog functions (ANx)
are forced to be an analog input.(look at this note)
ADCON1
<ADCS2>
ADCON0
<ADCS1:ADCS0>
Clock Conversion
0 00 FOSC/2
0 01 FOSC/8
0 10 FOSC/32
0 11 FRC (clock derived from the internal A/D RC oscillator)
1 00 FOSC/4
1 01 FOSC/16
1 10 FOSC/64
1 11 FRC (clock derived from the internal A/D RC oscillator)
A = Analog input D = Digital I/O
C/R = # of analog input channels/# of A/D voltage references
 

Thread Starter

abo zaynab

Joined May 1, 2018
35
trisa=0x3f;
trisb=0x00;portb=0x00;
trisc=0xff;
trisd=0xff;
trise=0x07;
InitTimer0();
cmcon=0x07;
ADCON0=0b11000001;
ADCON1=0b10001110;
delay_ms(2000);
and i used both codes to read analog pin0
wlevel=adc_read(0); (it reads fine but other analog pins reads as float)
if(GO_bit==1){
wlevel=ADRESH+ ADRESL ;}(it doesnt read right readings idk why)
delay_ms(1);
 

trebla

Joined Jun 29, 2019
542
To be sure that result will be contain both registers information concatenated to 16 bit integer is better to add casting operator :

wlevel = ((int)((ADRESH << 8) + ADRESL));

where wlevel should be declared as int. If you want display result as float you better use different float-type variable for it.
 
Top