Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

hope anyone can help me

Status
Not open for further replies.

congdi

New Member
i am doing a project with PIC16f877a via i2c to control the si570
the pic is put on the matrix multimedia version 3 development board.
now i want to change the frequency by press the button on the board.
for example: when i press button SA0, the frequency should change
but i dont know how to write the code. the button SA0 is connected to the RA0 of the PIC.
any one can help me?
here is my code
Code:
#include <math.h>
#include <16f877afloat.h>
#include <pic16f877a.h>
//#include <pic.h>
#include "i2c.h"

#define fout_start_up  56.5   // in MHz
#define frequency_list_length   20
#define POW_2_16          65536.0         //these must be floating point number                                       
#define POW_2_24          16777216.0      //especially 2^28 so that there is enough 
#define POW_2_28          268435456.0     //memory to use them in thecalculation
#define fxtal   114.285 ;     // in MHz

static bank2 float FXTAL; 
static bank2 unsigned char  j;                                   
static bank2 unsigned char  INITIAL_N1;
static bank2 unsigned char  INITIAL_HSDIV;
static bank2 signed long  INITIAL_RFREQ_LONG;                             
static bank2 unsigned long  FRAC_BITS;         // Double Floating Point Precision Method
static bank2 unsigned int  CURR_FREQ;          // Holds the index of the current frequency
                                               // being output
static bank2 unsigned char  reg[6];
static bank2 unsigned char  R137;
static bank2 const float  fdco_max  =  5670;   // in MHz
static bank2 const float  fdco_min  =  4850;   // in MHz
static bank2 const unsigned char bank2 HS_DIV[6] = {11, 9, 7, 6, 5, 4};
static bank2 float  rfreq;
static bank2 const float  fout0 = fout_start_up;
static bank1 float  fout1 [frequency_list_length] = 
{27.000000 ,  
 74.175824 ,
 100.000000 ,
 125.000000 ,
 161.132813 ,
 172.642300 ,
 200.000000 ,
 212.500000 ,
 368.640000 ,
 491.520000 ,
 622.080000 ,
 644.531250 ,
 666.514286 ,
 690.569196 ,
 704.380580 ,
 800.000000 ,
 933.120000 ,
 1000.000000 ,
 1400.000000 ,
 fout_start_up };                       
 
//-----------------------------------------------------------------------------
// SetBits
//-----------------------------------------------------------------------------
//
// Return Value : unsigned char
// Parameters   :
//   1) unsigned char original - original state of variable to be changed
//
//   2) unsigned char reset_mask - contains mask of bits that will reset the
//                  the original char variable.
//
//   3) unsigned char new_val - contains a mask of bits that need to be set in
//                     the original variable.
//
// This function sets appropriate bits in an unsigned char variable
//
unsigned char SetBits(unsigned char original, unsigned char reset_mask, unsigned char new_val)
{
   return (( original & reset_mask ) | new_val );
}


void FreProg (void)
{
   static bank2 int i;                             // temporary variable used in for loops
   static bank2 unsigned char n1;                  // Output divider that is modified and used in
                                                   // calculating the new RFREQ
   static bank2 unsigned char hsdiv;               // Output divider that is modified and used in
                                                   // calculating the new RFREQ
   static bank2 unsigned char reg137;              // Stores the contents of Register 137
                                                   // on Si57x
   static bank2 unsigned char validCombo;          // Flag that is set to 1 if a valid combination
                                                   // of N1 and HS_DIV is found
   static bank2 unsigned int divider_max;          // Maximum divider for HS_DIV and N1 combination
   static bank2 unsigned int curr_div;             // Minimum divider for HS_DIV and N1 combination
   static bank2 unsigned int whole;                // Used in Double Floating Point Precision Method
   static bank2 unsigned long final_rfreq_long;    // Final REFREQ that is sent to the Si57x
   static bank2 float curr_n1;                     // Used to calculate the final N1 to send to the
   static bank2 float n1_tmp;                      // Si570
   static bank2 float ratio = 0;                   // Will hold the final ratio to multiply the initial
                                                   // REFREQ by to acheive the final RFREQ

	// find dividers (get the max and min divider range for the HS_DIV and N1 combo) 
   divider_max = floor(fdco_max / fout1[CURR_FREQ]); //floorf for SDCC 
   curr_div = ceil(fdco_min / fout1[CURR_FREQ]);     //ceilf for SDCC
   validCombo = 0;

   while (curr_div <= divider_max)
   {
      //check all the HS_DIV values with the next curr_div
      for(i=0; i<6; i++)
      {
         // get the next possible n1 value
         hsdiv = HS_DIV[i];
         curr_n1 = (curr_div * 1.0) / (hsdiv * 1.0);
         // Determine if curr_n1 is an integer and an even number or one
         // then it will be a valid divider option for the new frequency
         n1_tmp = floor(curr_n1);
         n1_tmp = curr_n1 - n1_tmp;
         if(n1_tmp == 0.0)                     // Then curr_n1 is an integer
         {
            n1 = (unsigned char) curr_n1;
            if( (n1 == 1) || ((n1 & 1) == 0) ) // Then the calculated N1 is
            {                                  // either 1 or an even number
               validCombo = 1;
            }
         }
         if(validCombo == 1) break;            // Divider was found, exit loop
      }
      if(validCombo == 1) break;               // Divider was found, exit loop

      curr_div = curr_div + 1;                 // If a valid divider is not found,
                                               // increment curr_div and loop
      }


   // If validCombo == 0 at this point, then there is an error
   // in the calculation. Check if the provided FOUT0 and FOUT1
   // are valid frequencies
   // old method for New RFREQ calculation

   rfreq = (fout1[CURR_FREQ] * n1 * hsdiv) / fxtal;

   // Calculate RFREQ organizing the float variables to save precision;
   // RFREQ is kept as an unsigned long
   // only 32 bits are available in the long format
   // RFREQ in the device has 34 bits of precision
   // only 34 of the 38 bits are needed since RFREQ is between 42.0 and
   // 50.0 for fxtal of 114.285MHz (nominal)
   ratio = fout1[CURR_FREQ] / fout0;               // Try to keep ration near 1
                                              // to maintain precision
   ratio = ratio * (((float)n1)/((float)INITIAL_N1));
   ratio = ratio * (((float)hsdiv)/((float)INITIAL_HSDIV));
   final_rfreq_long = ratio * INITIAL_RFREQ_LONG; // Calculate final RFREQ value
                                                  // using ratio computed above

   for(i = 0; i < 6; i++)
   {
      reg[i] = 0;             //clear registers
   }

   hsdiv = hsdiv - 4;         // Subtract 4 because of the offset of HS_DIV.
                              // Ex: "000" maps to 4, "001" maps to 5
   
   //reset this memory
   //reg[0] = 0;
   //set the top 3 bits of reg[0] which will correspond to Register 7 on Si570
   reg[0] = (hsdiv << 5);


   // convert new N1 to the binary representation
   if(n1 == 1)
   {
      n1 = 0;  //Corner case for N1. If N1=1, it is represented as "00000000"
   }
   else if((n1 & 1) == 0)
   {
      n1 = n1 - 1; // If n1 is even, round down to closest odd number. 
    }              
   // Write correct new values to reg[0] through reg[6]
   // These will be sent to the Si570 and will update the output frequency
   reg[0] = SetBits(reg[0], 0xE0, (n1 >> 2));         // Set N1 part of reg[0]
   reg[1] = (n1 & 3) << 6;                            // Set N1 part of reg[1]
   //Write new version of RFREQ to corresponding registers
   reg[1] = reg[1] | (final_rfreq_long >> 30);
   reg[2] = final_rfreq_long >> 22;
   reg[3] = final_rfreq_long >> 14;
   reg[4] = final_rfreq_long >> 6;
   reg[5] = final_rfreq_long << 2;


   
   // Double Floating Point Precision Method
   // convert new RFREQ to the binary representation
   // separate the integer part
   whole = floor(rfreq);

   // get the binary representation of the fractional part
   FRAC_BITS = floor((rfreq - whole) * POW_2_28);

   // set reg 12 to 10 making frac_bits smaller by
   // shifting off the last 8 bits everytime
   for(i=5; i >=3; i--)
   {
      reg[i] = FRAC_BITS & 0xFF;
      FRAC_BITS = FRAC_BITS >> 8;
   }
   // set the last 4 bits of the fractional portion in reg 9
   reg[2] = SetBits(reg[2], 0xF0, (FRAC_BITS & 0xF));
   // set the integer portion of RFREQ across reg 8 and 9
   reg[2] = SetBits(reg[2], 0x0F, (whole & 0xF) << 4);
   reg[1] = SetBits(reg[1], 0xC0, (whole >> 4) & 0x3F);
   Freeze();
   Read_Si570();
   Unfreeze();
   NewF();
 }     






void ReadStartUpConfiguration (void)
{
int i;
recall();
Read_Si570();


INITIAL_HSDIV = ((reg[0] & 0xE0) >> 5) + 4; // Get value fo INITIAL_HSDIV from REG[0]
                                            // 4 is added to this because the bits "000" correspond to an HSDIV of 4, so there is
                                            // an offset of 4. See the register 7 of Si570 datasheet for more information.
INITIAL_N1 = (( reg[0] & 0x1F ) << 2 ) + (( reg[1] & 0xC0 ) >> 6 );
// Get correct value of INITIAL_N1 by adding parts of REG[0] and REG[1]
if(INITIAL_N1 == 0)
{
INITIAL_N1 = 1; // This is a corner case of N1
}
else if(INITIAL_N1 & 1 != 0)
{
INITIAL_N1 = INITIAL_N1 + 1; // As per datasheet, illegal odd divider values should
                             // be rounded up to the nearest even value.
}
// Double Floating Point Precision Method
// RFREQ conversion (reconstruct the fractional portion (bits 0 to 28) from the registers)
// (this method requires double precision floating point data type to be accurate)
FRAC_BITS = (( reg[2] & 0xF ) * POW_2_24 );
FRAC_BITS = FRAC_BITS + (reg[3] * POW_2_16);
FRAC_BITS = FRAC_BITS + (reg[4] * 256);
FRAC_BITS = FRAC_BITS + reg[5];
rfreq = FRAC_BITS;
rfreq = rfreq / POW_2_28;

// Read initial value for RFREQ. A 34-bit number is fit into a 32-bit space
// by ignoring lower 2 bits.
INITIAL_RFREQ_LONG = ( reg[1] & 0x3F );
INITIAL_RFREQ_LONG = (INITIAL_RFREQ_LONG << 8) + ( reg[2] );
INITIAL_RFREQ_LONG = (INITIAL_RFREQ_LONG << 8) + ( reg[3] );
INITIAL_RFREQ_LONG = (INITIAL_RFREQ_LONG << 8) + ( reg[4] );
INITIAL_RFREQ_LONG = (INITIAL_RFREQ_LONG << 6) + ( reg[5] >> 2 );
// RFREQ conversion (reconstruct the integer portion from the registers)
rfreq = rfreq + ( (( reg[1] & 0x3F ) << 4 ) + (( reg[2] & 0xF0 ) >> 4 ) );
// Crystal Frequency (FXTAL) calculation
FXTAL = (fout0 * INITIAL_N1 * INITIAL_HSDIV) / rfreq; 
}



   
//-----------------------------------------------------------------------------
// Port_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the Crossbar and GPIO ports.
//
// RC4   SDA
// RC3   SCL
// RA1   Used as input switch 'next' on board
void port_init()
  {
    TRISA=0X00;                     //set A as input                
    TRISC=0X00;
    PORTA=0XFF;                                          
    PORTC=0XE7;                     
   }





void main()
{ 
   int i;
   port_init(); 

   CURR_FREQ = frequency_list_length - 1; // Start up frequency is the last element in the array.
                                                             // Set CURR_FREQ index to point to last element
   ReadStartUpConfiguration();
   
   CURR_FREQ = 0; // After 'next' is pressed, first frequency element in FOUT1
                             // will be output
  

  while(1) // Loop forever  
   {
     while(!RA4)
    {
     //delay(300ms);
     FreProg();
     CURR_FREQ = CURR_FREQ + 1; // Update index for next frequency
     if (CURR_FREQ > (frequency_list_length - 1))
     {
      CURR_FREQ = 0; // Wrap around index after overflow
     }
    }
   }
 
while(1) // Loop forever
{
while(!RA4)
{
//delay(300ms);
FreProg();
CURR_FREQ = CURR_FREQ + 1; // Update index for next frequency
if (CURR_FREQ > (frequency_list_length - 1))
{
CURR_FREQ = 0; // Wrap around index after overflow
}
}
}
this is code i write in the main.
at the bottom of the code.
 
Status
Not open for further replies.

Latest threads

Back
Top