Unable to cope with a tiny 12F675.

Status
Not open for further replies.

swapan

Full Member level 4
Joined
Feb 20, 2009
Messages
204
Helped
27
Reputation
54
Reaction score
24
Trophy points
1,298
Location
Kolkata
Visit site
Activity points
2,839
Hi,
I am presently doing some practical test of peripheral of PIC 12F675. While trying to use analogue comparator, a weird result is noticed. I have made a circuit with 12F675 connected as follows.

GP 0 used as ADC as well as CIN- for comparator.
GP 1 used as output for LED_1
GP 2 used as output for LED_2
GP 3 not used.
GP 4 not used.
GP 5 used as output for LED_3.

Vdd i.e. +5v is applied to GP 0 for ADC through 10K pot.
I want to just see if ADC as well as comparator function is done by PIC simultaneously.

When ADC supply is varied though pot, LED_2 and LED_3 works as usual. But LED_1 connected to GP 1 does not work. I have scrutinized the code as well as hardware, but found no fault. At last I deactivated the comparator peripheral. Now all the LEDs work well.

Since I have utilized internal reference and GP 0 multiplexed to comparator INV input the GP1 should work as Digital IO. But it is not working when comparator function is activated.

Please see my code and suggest.

Code:
sbit LED_1 at GP1_bit;
sbit LED_2 at GP2_bit;
sbit LED_3 at GP5_bit;
unsigned int AD_Average;

void Init(void){
GPIO = 0x0;
TRISIO = 0b00001001;
ANSEL = 0x51;  //   TAD  = 16Tosc
CMCON = 0x1E;   // Analogue comparator used with internal ref.
VRCON = 0xA1;    // Reference set in lowest value.
             }
void main()   {
Init();
while(1)
{
Delay_ms(500);
ADC_Read(0);
if (AD_Average < 250)   {
LED_1 = 0;
LED_2 = 0;
}

else if (AD_Average < 420)  {
LED_1 = 0;
LED_2 = 1;
 }
 else if (AD_Average < 650){
 LED_1 = 1;
 LED_2= 0;
                          }
                          
else   {
LED_1 = 1;
LED_2 = 1;
       }
       }
                      }
 

Hi,
i never worked with it's comparator, but as i remember from electronic class a comparator changes it's output from 0 to 1 depending by the difference of the input and a reference. So why do you make an ADC acquisition , shouldn't you check a bit in a register related to the comparator?
Or in an other way:
I see that you use ADC , so why do you activate the comparator?
An other remark is that the AD_average value that you compare to in if conditions might be always 0 or any number since it's declared but not initialized. Is the AD_Average the place where ADC result is stored by read function ?
 
Last edited:

Thanks zsolt1 for your reply and also pointing out a serious mistake in the code. Actually, I made the mistake while posting the code. The modified code as follows. As per datasheet of 12F675, I have used GPIO bit 0 as CIN- of comparator module leaving GPIO bit 1, and GPIO bit 2 free, which is CIN+ and COUT respectively of the comparator. The ADC module is functioning as expected - LED_2 and LED_3 showing output. But LED_1 i.e. GPIO bit 1 (CIN- bit) is not responding. As per datasheet, I have configured comparator such that GPIO bit 1 be free from this module. Hence it should act as Digital I/O.

No specific purpose is intended, rather I like to test various peripheral of MCU.

Code:
sbit LED_1 at GP1_bit;
sbit LED_2 at GP2_bit;
sbit LED_3 at GP5_bit;
unsigned int AD_Average;

void Init(void){
GPIO = 0x0;
TRISIO = 0b00001001;
ANSEL = 0x51;  //   TAD  = 16Tosc
CMCON = 0x1E;   // Analogue comparator used with internal ref.
VRCON = 0xA1;    // Reference set in lowest value.
             }
void main()   {
Init();
while(1)
{
Delay_ms(500);
AD_Average = ADC_Read(0);
if (AD_Average < 250)   {
LED_1 = 0;
LED_2 = 0;
}

else if (AD_Average < 420)  {
LED_1 = 0;
LED_2 = 1;
 }
 else if (AD_Average < 650){
 LED_1 = 1;
 LED_2= 0;
                          }
                          
else   {
LED_1 = 1;
LED_2 = 1;
       }
       }
                      }
 

Your if conditions are wrong.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (AD_Average < 250)   {
                  LED_1 = 0;
                  LED_2 = 0;
          }
 
          else if (AD_Average < 420)  {
                  LED_1 = 0;
                  LED_2 = 1;
          }
          else if (AD_Average < 650){
                  LED_1 = 1;
                  LED_2 = 0;
          }
          else   {
                  LED_1 = 1;
                  LED_2 = 1;
          }



If AD_Average is < 250 then it is also < 420 and 650 so 3 conditions except the last else gets executed one by one

You should use something like


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (AD_Average < 250)   {
                  LED_1 = 0;
                  LED_2 = 0;
          }
 
          else if (AD_Average >= 250)  && (AD_Average < 420)  {
                  LED_1 = 0;
                  LED_2 = 1;
          }
          else if (AD_Average >= 420)  && (AD_Average < 650){
                  LED_1 = 1;
                  LED_2 = 0;
          }
          else   {
                  LED_1 = 1;
                  LED_2 = 1;
          }




You can't use ADC and Comparators at the same time. You have to time share. You enable ADC and disable Comparator and read ADC then disable ADC and enable Comparator and use it.
 

What compiler do you use ? I'm not familiar with now days fancy compilers with all those ready to use predefined functions. I recently discovered Arduino , they have libraries for almost everything (wire/wireless communication, timers, signal acquisition ...). It's really easy and fast to implement something on it.
 

When ANSEL bit 0 is made 1 then ADC is turned ON and if TRISIO bit 0 is 1 then GPIO0 will become an Analog Input but for GPIO0 to work in Comparator mode it should be set ad digital input and not Analog input.

There is a problem. CVref connects internally to Non Inv Input (+) of Analog Comparator and this (+) input also connects to GPIO0. So when you use internal CVref for Comparator then Cin- (Inverting input) has to be supplied with some test voltage and used as input but it is configured as output and connected to LED. Move GPIO1 LED to GPIO4 and try.

- - - Updated - - -

I have written a code but ADC and Comparator are used as time sharing not simultaneous. Cin- is GPIO1 and GPIO0 is only used for ADC mode. In Comparator mode GPIO0 is not used. CVRef is provided internally to Cin+ pin. When Cin- is > Cin+ (CVRef) LED at GPIO2 (COUT) turns ON. If you use different pins for ADC LEDs and Comparator output LEDs then time sharing will be of use and you can remove the delays in the code and it appears as both are working simultaneously.

Proteus 8.1 simulation file is attached.
 

Attachments

  • ADC COMP.rar
    44.4 KB · Views: 71
Last edited:

If AD_Average is < 250 then it is also < 420 and 650 so 3 conditions except the last else gets executed one by one

I have a little knowledge on C. The book that I follow for this language explained somewhere in decision making chapter that in case of else if ladder, when a condition is satisfied, rest condition(s) are not tested. Hence I thought that if AD_Average < 250, other conditions though they are also satisfied, would not be tested. However, in practical test this code works without problem except that the GPIO1 does not respond.

- - - Updated - - -

Hi zsolt1, I use mikroC pro compiler
 

GPIO1 is configured as Output in your code but it is Cin- for Comparator Circuit. Cin+ is internally connected to CVRef. So, Cin- (GPIO1) has to be provided the test voltage. In your case it is connected to LED and used as output ? When Cin+ (Internal CVRef) is provided how are you providing test voltage to Cin- ?

- - - Updated - - -

Yes, you are right. Your if...elseif() condition is ok but if the order of checking is reversed it will not work. Try debugging this piece of code in mikroC Compiler.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
AD_Average = 150;
          
          if (AD_Average < 650)   {
                  LED_1 = 0;
                  LED_2 = 0;
          }
          else if (AD_Average < 420) {
                  LED_1 = 0;
                  LED_2 = 1;
          }
          else if (AD_Average < 250) {
                  LED_1 = 1;
                  LED_2 = 0;
          }
          else {
                  LED_1 = 1;
                  LED_2 = 1;
          }



Even if ADC value is 150 the 1st condition if adc value < 650 is executed and others skipped. It will result in incorrect decision. It is better to use the code which I have provided. That way the right decision will execute whatever be the order of execution.
 


As per datasheet inverting input of comparator is selectable - multiplexing CIN- and CIN+. Configuring CMCON register, I have linked inverting input of comparator to CIN+ and left CIN- free. Test voltage is given to inverting input through CIN+ i.e. GPIO0.
 

I will check and reply. What is the value of CVRef you are providing ? (1 / 24) * 5 = 0.208 ? Try 0xAF for VRCON which gives CVRef of (15 / 24) * 5 = 3.125 V.
 

Now the ADC and Comparator both work fine. I don't know how you said that ADC works fine when you had not configured ADCON0. Read comments in code.


COUT is connected to GP2 and you see it as blinking when 5V (anything greater than 3.125V) is applied to GP0 which is Cin- as CIS bit = 1. Blinking occurs because Comparator is turned ON/OFF using CMCON.
 

Attachments

  • ADC COMP rev1.rar
    61.7 KB · Views: 77

What is the value of CVRef you are providing ? (1 / 24) * 5 = 0.208 ? Try 0xAF for VRCON which gives CVRef of (15 / 24) * 5 = 3.125 V.

Yes, the smallest value of CVRef is used. Does it really matter for its operation when there is provision of using CVRef from smallest to highest value?


I don't know how you said that ADC works fine when you had not configured ADCON0

I think for mikroC compiler, you need not to configure ADCON0 register. I made number of tests involving ADC peripheral of MCU without configuring ADCON0 and they all works well. You may also test this aspect practically.

COUT is connected to GP2 and you see it as blinking when 5V (anything greater than 3.125V) is applied to GP0 which is Cin- as CIS bit = 1.

Please go through datasheet. CMCON registered has been configured in a way so that COUT is disconnected from GP2. Though I am a novice in this subject, but I am sure the LEDs turn ON/OFF as ADC function works. Please note LEDs are there in other bits also. As you opined LED blinks due to comparator, then only LED connected to GP2 will be effected leaving others static. But the result is not like that. All the LEDs act as per the algorithm.
 

Did you read my code. I have changed the LED sbit defines. I changed LED_3 to GP2 as it is connected to COUT. If you use LED at GP2 for ADC then you will not be able to output the status of COUT. I tried like


Code C - [expand]
1
LED_3 = COUT

when LED_3 was GP5 but it didn't work and so I had to use GP2 for COUT. What is the problem you have with my code. You can change to Low Range (VRR bit = 1) and VR3:VR0 = 0001 which gives (1 / 24) * 5 for CVRef. I tested the working in Proteus and not in read hardware, thats why I used CVRef of 3.125 V as pot model was not working properly.


The GP2 LED_3 blinks because CMCON has two values

Code C - [expand]
1
CMCON = 0x07 to disable Coparator during ADC operation and CMCON = 0x1D for Comparator operation



When Comparator is turned ON ADC will not work.

As you opined LED blinks due to comparator, then only LED connected to GP2 will be effected leaving others static. But the result is not like that. All the LEDs act as per the algorithm.

See I am not clearing the GPIO, so once the ADC leads are turned ON they remain in ON state even during Comparator mode but LED_3 GP2 connected to COUT blinks because when CMCON is made 0x07 then Comparator is disabled and hence its output COUT goes low or maybe undefined state.
 
Last edited:

Thanks milan.rajik for your reply. It is clear that the way I am carrying out the test differs from that of you. I like the ADC as well as Comparator module work simultaneously. But your given code shows this one after other.
 

Both cannot work simultaneously. Comparator has to be disabled for ADC to work properly and ADC has to be disabled for Comparator to work properly.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…