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.

PIC16f676 Intenall Oscilator problem.

Status
Not open for further replies.

dani

Full Member level 4
Joined
Mar 8, 2004
Messages
231
Helped
6
Reputation
12
Reaction score
4
Trophy points
1,298
Location
UK
Activity points
2,217
_read_osccal_data

Hello all,

I have written a code to generate 50 hz flip flop pulses through PIC16F676. I have used internal oscilator for this. The results are not comming correct in terms of pulse timings(width). it seems that some pic after programming work well and on another it doesnt. Is this due to internal oscilator or am i doing some thing wrong some where . Plz Help.


Regards
Dani
 

pic16f676 programmer

The internal oscillator is calibrated and has the calibration recorded .
A good programmer read the value before reprogramming and reestablishes it
If you have a factory programmer it will be so .
If you are using another programmer it might not record the calibration byte and will change its frequency.
There is also an Oscal register to tune the oscillator
In addition there is a way to read the OSCAL
register(0x90)before starting the progarm and so be sure to always use the same frequency.

But mind that the oscillator ,if my memory serves me right ,is +/- 1 % accurate.

The subroutine to read calibration byte before destroying it

cal:

ASM: bsf STATUS,RP0
ASM: call 0x3ff
ASM: movwf OSCCAL
ASM: bcf STATUS,RP0
Return

Note :1/All that can be found in the data sheet
2/ you must be sure hat your program does follow the same path all the time ,if you dont use an interrupt to generate your signal
Good luck
 

pic16f676 internal oszillator

gebepic said:
The internal oscillator is calibrated and has the calibration recorded .
A good programmer read the value before reprogramming and reestablishes it
If you have a factory programmer it will be so .

My programmer alway asks me to write 34 hex value for calibration. and not any other value i donot know why.

below is my code..

Code:
[code]
#include "D:\CURRENT_PROJECTS\UPS\pp676.h"
#define BttlowInd     PIN_C5
#define RelayBttChrg  PIN_C2
#define UPSLED        PIN_C3
#define LEdWapda      PIN_A4
#define PUSH          PIN_C4
#define PULL          PIN_C1
#define WapdaIn       PIN_A5
#define Buzzer        PIN_A3
#define FAN           PIN_C0
#define BttCh 1   
#define MainCh 0

int1 Flg,WapdaFlg=0,FlgChrg,FlgUps=0,chrgFlg=0,tflg = 0,jOflg = 0,shutFlg = 0,sflg=0,BFLG1=0,BFLG2=0,bFlg3=0; 
int16 BttVolt,DelayTime,DTT=2400,Ltime=0,dt,chrgCounter=0,d,sCounter = 0,shutcounter=0,bcounter=0,blCounter=0;
INT8 BUZZFLG = 0;
void SetBttVolt(void);
void WapdaCheck(void);
void doWapdaAbsent(void);
void doWapdaPresent(void);
void SetDelayTime(void);
void doShutDown(void);


#int_TIMER1
void  TIMER1_isr(void) 
{
 scounter++;  
 d++;
 
 if((WapdaFlg==0) && (FLgUps==1)){ // WAPDA IS ABSENT BUT UPS IS WORKING DUE TO BATT VOLTAGE ABOVE 2.0
//   printf("%ld,%ld\r",ltime,dtt);
   if (LTime==0)
      LTime = 1;
      dt = dTT - 3000;
         if(dTT >= 3000){
            output_high(PUSH);
            delay_us(dt);
         }
      output_low(PUSH);
      delay_us(Ltime);
      

      delay_us(100);  //dead gap at end of c2

         
      output_low(PULL);
      delay_us(Ltime);
      

      delay_us(100);  //dead gap at end of c2

      
      
      output_high(PULL);
      delay_us(2000); // fix 5ms high time
      delay_us(dT);
      
      output_low(PULL);
      delay_us(Ltime);
      

      delay_us(100);  //dead gap at end of c2

      
      
      delay_us(Ltime);
         

      delay_us(100);  //dead gap at end of c2

      
      output_high(PUSH);
 }

 else{
      output_low(PUSH);
      output_low(PULL);
     
 }

 set_timer1(63533); // fix 3ms delay
 IF(BUZZFLG>0)
 {
   BUZZFLG--;
   OUTPUT_HIGH(BUZZER);
   bflg1 = 1;
   bflg2 =1;
   bflg3 = 1;
 }ELSE{
   OUTPUT_LOW(BUZZER);
   bcounter++;
   //printf("%ld\r",bcounter);
 }
 
}



void main()
{
   int16 i=0;
   Flg = 0;
   FlgUps=0;
   WapdaFlg = 0;
   set_tris_a(0b100011);
   output_c(0);
   output_low(pin_a2);
   output_low(pin_a3);
   output_low(pin_a4);   
   
   setup_adc_ports(sAN0|sAN1|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
   
   output_high(LEDWAPDA);
  // output_high(UPSled);
   //output_low(pin_a4);   
   
   If(!input(WAPDAIN)){
         wapdaFlg = 1;
         Flgups = 0;
         enable_interrupts(INT_TIMER1);
         enable_interrupts(GLOBAL);
   }else{
         wapdaFlg = 0;
         Flgups = 1;
         SetDelayTime();
         enable_interrupts(INT_TIMER1);
         enable_interrupts(GLOBAL);
         while(d<100){
            SetDelayTime();
         }
         
   }
  
         

/*   for(i=10;i>1;i--){
      SetBttVolt();
      WapdaCheck();
      if (WapdaFlg){
         
         doWapdaPresent();
      }else{//if waPDA IS ABSENT
          doWapdaAbsent();          
      }
      delay_ms(1);
      Ltime = 2400;
      dTT = 5000;
   }*/
   
    while (1){
  
      SetBttVolt();
      WapdaCheck();
    
       if(shutFlg == 0){
         if (WapdaFlg){
            
            doWapdaPresent();
            bflg1=0;
            //bflg3=0;
         }else{//if waPDA IS ABSENT
            doWapdaAbsent();
            bflg2=0;
         }
       }else
       {
         doShutDown();
       }
         SetDelayTime();
   }//while
   
   

}

void SetDelayTime(){
      int16 t;
      INT16 Tempf;
      set_adc_channel(MAINCH);
      delay_us(20);
      t = read_adc();
      
      If (t <= 327){        // 1.0v for 9.8ms pulse
         DelayTime = 9800;
      }Else if (t >= 491){   // 2.0v for 3.0ms pulse
            DelayTime = 3000;
      }Else{
          t = 491 - t;
          TempF = t * 41; // conversion for 245 to 6800ms
          DelayTime = 3000 + TempF;                   
       }
     DTT = DELAYTIME;
     LTIME = (9800 - DTT)/2;
   //  printf("%ld\r",dtt);        
}

void WapdaCheck(){

     If(!input(WAPDAIN)){     //        'Wapda present
         
         while( d < 100 && !input(WAPDAIN)){
         //       printf("%ld\r",d);
         }
         
        if(d>=100){   
            WapdaFlg = 1;
            flg = 0;
            output_low(PUSH);
            output_low(PULL);
            output_Low(BttLowInd);
            output_LOW(LedWapda);
            shutFlg = 0;
            d=101;
//            printf("-----------0\r");
         }
     }Else{
        WapdaFlg = 0;
        d=0;
        output_Low(RelayBttChrg);
        output_HIGH(LedWapda);
        output_low(FAN);
//        printf("-----------1\r");
     }
 }
 
 void SetBttVolt(){
      set_adc_channel( BTTCH );
      delay_us(20);
      BttVolt = read_adc();
  }
  
  void doWapdaAbsent(){
      if(bflg1==0)
      {
         buzzflg = 500;   
      }
      jOflg = 0;   
      chrgcounter=0;
      output_Low(RelayBttChrg);
      output_LOW(UPSLED);
      output_high(FAN);
      chrgflg = 0;
      chrgCounter=0;
      FlgUps = 1;
//      printf("-----------b\r");
       If (BttVolt < 368){    //        'Battery is too low. At 10v (on ADC 1.8) shutdown UPS 
         shutcounter++;
         if(shutcounter>100){
            shutcounter=0;
            output_HIGH(UPSLED);
            output_low(buzzer);
            shutFlg = 1;
         }
       }else if(BttVolt < 409 ){    // '21v (on ADC 2.1v) Low battery indication
         blcounter++;
         if(blcounter>100){
            blcounter=0;
            output_high(BttLowInd);
            shutcounter=0;
            if(bflg3==0)
            {
               buzzflg = 500;
               bcounter = 0;
            }else if(bcounter > 1000)
            {
               bcounter=0;
               bflg3=0;
            }
         }
         
       }else{
         shutcounter=0;
         blcounter=0;
       }
         
  }
  
  void doWapdaPresent(){
      if(bflg2==0)
      {
         buzzflg = 250;   
      }

         output_High(UPSLED);
//         printf("-----------c,%ld\r",bttvolt);
         
         If (BttVolt > 572){ //         'Voltage exceeds 27v (on ADC 2.7v) then  cut charging
            output_Low(RelayBttChrg);
            output_low(FAN);
            chrgflg==0;
            
         }
         Else If (BttVolt < 491 && joFlg ==1 ){     //   'Voltage 12v when charging starts   
           
               output_High(RelayBttChrg);
               output_high(FAN);
               output_low(BttLowInd);
               chrgflg=1;
               
          
         }Else If (BttVolt < 572 && joFlg ==0 ){     //   'Voltage 26v when charging starts   
            chrgCounter++;
//            printf("**chc = %ld\r",chrgCounter);
            if(chrgflg==0 && chrgCounter>10000){
               output_High(RelayBttChrg);
               output_high(FAN);
               output_low(BttLowInd);
               chrgFlg=1;
               jOflg=1;
               chrgcounter=10001;
            }
         }
  }
  
  void doShutDown(){
      FLgUps=0;
      jOflg = 0;
      chrgcounter=0;
      shutcounter=0;
      if(sflg == 0 && scounter > 100)
      {
         output_high(bttLowInd);
         scounter = 0;
         sflg = 1;
         //printf("-----------\r");
      }else if(sflg == 1 && scounter > 100){
         output_low(bttLowInd);
         scounter = 0;
         sflg = 0;
//         printf("***************\r");
      }
  }
      


The above is the complete code for a ups opreation. 

But my questin was bit general in a sense that may be

1 - I dont know how to use internall oscilator or How to calibrate it.

2 - If i use Timer1 interrupt to generate fixed interval interrupt for generating 50Hz flip folp pulses. Is it possible in 16f676 with internall oscilator or not.

Because 
3- I have used the same code in 16f877a with external crystal oscialator and results are seme with evey chip, But this is not the case while is use 16f676 and internall oscillator. So where i am doing wrong.
 
programme pic 16f676 void

dani said:
gebepic said:
The internal oscillator is calibrated and has the calibration recorded .
A good programmer read the value before reprogramming and reestablishes it
If you have a factory programmer it will be so .

My programmer alway asks me to write 34 hex value for calibration. and not any other value i donot know why.

The way I see it , every time you program another chip you destroy the factory calibration and replace it with 0x34.
That makes every chip work on a different frequency.
The frequency is adjustable by OSCCAL between certain limits , I do'nt remember what they are ,some few hundred Khz , I think(NOT SURE it must be checked in the data sheet or general data for those chips)

Assuming 100 KHz difference will give: 1 second /4*.1=25 milliseconds difference
or 2.5 %
and a few hundred KHz say 4 ==>> 25*4 =100 milliseconds or 10 %

If your code works with a Xtal there is , in my opinion(always challengeable) , no reason other than the above for the differences.

There is a way to recalibrate the oscillator(OSCCAL)but I cannot find it at the moment.An oscilloscope could help....
 

calibrate+pic16f676

i think your programmer is pufff!!! get it ?
 

pic16f676 internal clock frequency

What firm makes pufff ?
It would be nice to get it to test ...

Extracted from Data sheet of 676

9.2.5 INTERNAL 4 MHZ OSCILLATOR
When calibrated, the internal oscillator provides a fixed
4 MHz (nominal) system clock. See Electrical
Specifications, Section 12.0, for information on
variation over voltage and temperature.
Two options are available for this Oscillator mode
which allow RA4 to be used as a general purpose I/O
or to output FOSC/4.
9.2.5.1 Calibrating the Internal Oscillator
A calibration instruction is programmed into the last
location of program memory. This instruction is a
RETLW XX, where the literal is the calibration value.
The literal is placed in the OSCCAL register to set the
calibration of the internal oscillator. Example 9-1
demonstrates how to calibrate the internal oscillator.
For best operation, decouple (with capacitance) VDD
and VSS as close to the device as possible.
EXAMPLE 9-1: CALIBRATING THE
INTERNAL OSCILLATOR
Note: Erasing the device will also erase the preprogrammed
internal calibration value for
the internal oscillator. The calibration value
must be saved prior to erasing part as
specified in the PIC16F630/676 Programming
specification. Microchip Development
Tools maintain all calibration bits to
factory settings.

bsf STATUS, RP0 ;Bank 1
call 3FFh ;Get the cal value
movwf OSCCAL ;Calibrate
bcf STATUS, RP0 ;Bank 0

Final note ::: if the value has been erased ...??? !!! ??? pufff !!!:cry:

C Q F D. :D

Last EDIT

I have dug out some extra dope on the Pic mid range internal oscillator in the

PIcmicro Mid Range MCU Familly Reference manual(available at guess where ?)

There are 4 pages to read about it.

gebe
 

using pic16f676 with internal oscillator

Sory to bother you again, but sir i am still unable to figure out the solution.
If writing 0x34 is destroying the factory value, what to write then. If read before programming the chip then it gives 34 thats why i write 34.

If i get fresh chip without code and i read the calibiration what should i get, and should i write that value every time or this value will be new every time depending upon the configuration fuese.
 

pic16f676 problem

dani said:
Sory to bother you again, but sir i am still unable to figure out the solution.
If writing 0x34 is destroying the factory value, what to write then. If read before programming the chip then it gives 34 thats why i write 34.

If i get fresh chip without code and i read the calibiration what should i get, and should i write that value every time or this value will be new every time depending upon the configuration fuese.

sound like you are never inserting calibration value during programing in your hex file here is short tut how do that

regards
Fragrance
 

pic16f676 assembly example codes

Hello sweet fragrance. Hope you are doing fine.

I am unable to open the document you have posted here. Please provide the link or you can pm me again.
 

1% variation internal oscillator 4mhz

bsf STATUS, RP0 ;Bank 1
call 3FFh ;Get the cal value
movwf OSCCAL ;Calibrate
bcf STATUS, RP0 ;Bank 0

You might check the new generation of 14/18 pins, that will do the trick
I am using at the moment some 12 F683(8 pins , not enough for you)
They work with the internal osc up to 8 megs and also do not need to set the calibration value (there is none !)
Just put OSCTUNE on zero

Latest check , 16 F 684 should do , same pins nb as 676,more powerfull
Price could even be cheaper ...?
 

how to use pic16f676 internal oscillator

I am not telling what solution finaly i got , becuase it is yet to be verified first.

Thnak you Thank you and Thanks a lot to gebepic,. I am working on the issue and soon i will report on forum.

I also want to thank Fragrence for his wonderfull and intelegent contribution to solve my problem. He is realy very intelligent and catch me right there where i was stuck and told me the solution.

Any how it realy improved my knowldege pertaining to this perticular problem

Regards
Dani
 

sample hex code for pic16f676

Dear Dany,

I have downloaded the "teach" from the forum about the programmer
This is for programming the chip,it does NOT ensure a constant frequency for the internal oscillator !!!!!!!

EVEN IF YOU HAVE A VALID CALIBRATION SITTING IN YOU CHIP

IF YOU DO NOT USE IT BY THE FOLLOWING call:
(that you must include in your program)


as a subroutine .......CODED in C
the following is in ASM(I cannot CODE in your C)

something like this
void CalibSub()
{
//IN C Langage


}

CalibSub: bsf STATUS,RP0 ;set bank 1
Call 0x3FF ; get the calibration value
; The W register contains it automatically at return
; from there
movwf OSCCAL ; enter it in the REGISTER
bcd STATUS,RP0 ;back to bank 0
return

Or , If you want you can INLINE it (NO CALL)

by preceding every line with ASM: (if your C allows it)
like :

ASM: bsf STATUS,RP0 ;set bank 1
ASM: Call 0x3FF ; get the calibration value
ASM: ; The W register contains it automatically at return
ASM: ; from there
ASM: movwf OSCCAL ; enter it in the REGISTER
ASM: bcf STATUS,RP0 ;back to bank 0


Otherwise the OSCCAL , at every restart , may contain a random value wich will
make your timing RANDOM between the different values taken by OSCCAL !!!!
It is like all uninitiated variables in C.....UNPREDICTABLE

Good luck
 

programme example of pic16f676

Hello All

After so much head banging. I have tried the following solution and it worx. This problem is a newbie problem and can be resolved if following points are observed.

1- First of, All 16f676 come with a factory calibration and it is stored at 0x3ff. It is different for each pic. for example pic1 has calibration value as 10, pic 2 has 28. Both will generate exactly 4MHz at their factory settings. If you over-write this, assume pic1 with new value 20. Your clock will exceed 4MHz. If you write 05, clock will be less than 4MHz.

2- If you have erased this value, good luck then. You will need and oscilloscope and hit and try diff values to get back the calibration value.

3- This 0x3ff location will look sth like 34XX (XX being calibration value). 34 means RETLW instruction, do not change it as it is an opcode. You can change XX to achieve other frequencies if you want to, as explained in step1.

4- If you want to work exactly at 4MHz, Just read the OSCCAL value using instructions in datasheet for ASM. OR using PICC like me, put "OSCCAL = _READ_OSCCAL_DATA();" in main(); :). It will get the value and work at 4MHz exactly. Note that program needs this OSCCAL value as a variable to work precisely, if your program is frequency defendant.

4.1- Just a tip, PICC generates a warning on above OSCCAL code line. open pic16630.h and replace #define _READ_OSCCAL_DATA() (*(unsigned char(*)())0x3FF)() with #define _READ_OSCCAL_DATA() (*(unsigned char(*)(void))0x3FF)().

H
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top