⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 int_osc_measure1.c

📁 c8051f020开发板的所有参考程序
💻 C
字号:
//-----------------------------------------------------------------------------
// INT_OSC_Measure1.c
//-----------------------------------------------------------------------------
// Copyright 2002 Cygnal Integrated Products, Inc.
//
// AUTH: BW
// DATE: 02 APR 02
//
// This program shows an example of how the external oscillator
// can be used to measure the internal oscillator frequency.
//
// In this example, the internal oscillator is set to its highest setting.
// The external oscillator is configured to its desired mode (external
// 22.1184MHz crystal).  The PCA counter is used as a generic 16-bit counter 
// that uses EXTCLK / 8 as its time base.
// 
// We configure Timer0 to count SYSCLKs, and count the number of INTCLKs
// in 1 second's worth of EXTCLK/8
//
// Target: C8051F02x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <c8051f020.h>                 // SFR declarations
#include <stdio.h>
#include <math.h>

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F02x
//-----------------------------------------------------------------------------

sfr16 DP       = 0x82;                 // data pointer
sfr16 TMR3RL   = 0x92;                 // Timer3 reload value
sfr16 TMR3     = 0x94;                 // Timer3 counter
sfr16 ADC0     = 0xbe;                 // ADC0 data
sfr16 ADC0GT   = 0xc4;                 // ADC0 greater than window
sfr16 ADC0LT   = 0xc6;                 // ADC0 less than window
sfr16 RCAP2    = 0xca;                 // Timer2 capture/reload
sfr16 T2       = 0xcc;                 // Timer2
sfr16 RCAP4    = 0xe4;                 // Timer4 capture/reload
sfr16 T4       = 0xf4;                 // Timer4
sfr16 DAC0     = 0xd2;                 // DAC0 data
sfr16 DAC1     = 0xd5;                 // DAC1 data

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define EXTCLK       22118400          // EXTCLK frequency in Hz
#define BAUDRATE     9600              // Baud rate of UART in bps

sbit LED = P1^6;                       // LED = 1 means ON

//-----------------------------------------------------------------------------
// Structures, Unions, Enumerations, and Type definitions
//-----------------------------------------------------------------------------

typedef union ULong {
   long Long;
   unsigned int UInt[2];
   unsigned char Char[4];
} ULong;

//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void INTCLK_Measure (void);

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------

long INTCLK;                           // holds INTCLK frequency in Hz
long SYSCLK;                           // holds SYSCLK frequency in Hz

//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void main (void) {

   WDTCN = 0xde;                       // disable watchdog timer
   WDTCN = 0xad;

   SYSCLK_Init ();                     // initialize oscillator
   PORT_Init ();                       // initialize crossbar and GPIO

   EA = 1;                             // enable global interrupts

   INTCLK_Measure ();                  // measure internal oscillator and
                                       // update INTCLK variable
   SYSCLK = INTCLK;

   UART0_Init ();                      // initialize UART0

 
   while (1) {
      INTCLK_Measure ();               // measure internal oscillator and
                                       // update INTCLK variable
      printf ("INTCLK = %ld Hz\n", INTCLK);
   }
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clocks
//
void SYSCLK_Init (void)
{
   int i;                              // delay counter

   OSCXCN = 0x67;                      // start external oscillator

   for (i=0; i < 256; i++) ;           // wait for osc to start up

   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle

   OSCICN = 0x07;                      // configure internal oscillator at max
                                       // frequency;
                                       // set INTCLK as SYSCLK source
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PORT_Init (void)
{
   XBR0    |= 0x04;                    // Enable UART0
   XBR2    |= 0x40;                    // Enable crossbar and weak pull-ups
   P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output
   P1MDOUT |= 0x40;                    // enable LED as push-pull output
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1.
//
void UART0_Init (void)
{
   SCON0  = 0x50;                      // SCON0: mode 1, 8-bit UART, enable RX
   TMOD   = 0x20;                      // TMOD: timer 1, mode 2, 8-bit reload
   TH1    = -(SYSCLK/BAUDRATE/16);     // set Timer1 reload value for baudrate
   TR1    = 1;                         // start Timer1
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base
   PCON  |= 0x80;                      // SMOD00 = 1
   ES0    = 0;                         // disable UART0 interrupts
   TI0    = 1;                         // indicate ready for TX
}

//-----------------------------------------------------------------------------
// INTCLK_Measure
//-----------------------------------------------------------------------------
//
// This routine uses the external oscillator to measure the frequency of the
// internal oscillator.  Assumes that the external oscillator has been
// started and settled.  Also assumes that the internal oscillator operating
// at its highest frequency is selected as the system clock source.
//
// The measurement algorithm is as follows:
// 1. PCA set to '-1'; Timer0 set to 0x0000; PCA stopped; Timer0 stopped
// 2. PCA0 started (CR = 1)
// 3. On CF, Timer0 is started (TF0 = 1); CF is cleared, PCA0 remains running
// 4. When T0_high:Timer0 reach 0x00000000, stop PCA0
// 5. EXTCLK frequency = PCA0_high:PCA0
// Upon completion, the global variable EXTCLK contains the internal 
// oscillator frequency in Hz.
//
// I believe the worst-case measurement error is around 20 system clocks.
// 20 / 16e6 = 1.3 ppm (far less than typical crystal ppm's of 20)
//
void INTCLK_Measure (void)
{
   unsigned int T0_high;                  // overflow bytes of Timer0
   unsigned int PCA0_high;                // overflow bytes of PCA0
   ULong temp;                            // byte-addressable Long

   // PCA0 counts up to EXTCLK/8; PCA0_high is the upper 2 bytes of this number
   temp.Long = -(EXTCLK >> 3);
   PCA0_high = temp.UInt[0];
   PCA0CN = 0x00;                         // Stop counter; clear all flags
   PCA0MD = 0x0b;                         // PCA counts in IDLE mode;
                                          // EXTCLK / 8 is time base;
                                          // overflow interrupt is enabled
   PCA0L = 0xFF;                          // set time base to '-1'
   PCA0H = 0xFF;

   // Timer0 counts from zero to INTCLK

   // init Timer0
   CKCON |= 0x08;                         // Timer0 counts SYSCLKs
   TCON &= ~0x30;                         // Stop timer; clear TF0
   TMOD &= ~0x0f;                         // Timer0 in 16-bit counter mode
   TMOD |=  0x01;
   T0_high = 0x0000;                      // init Timer0
   TL0 = 0x00;
   TH0 = 0x00;

   // start PCA0
   CR = 1;
   while (CF == 0);                       // wait for edge
   TR0 = 1;                               // Start Timer0
   CF = 0;                                // clear PCA overflow
   PCA0L = temp.Char[3];
   PCA0H = temp.Char[2];

   while (1) {                            // wait for 1 second
      if (CF) {                           // handle PCA0 overflow
         PCA0_high++;
         if (PCA0_high == 0x0000) {       // check for completion
            TR0 = 0;                      // Stop Timer0
            break;
         }
         CF = 0;
      }
      if (TF0) {                          // handle T0 overflow
         T0_high++;
         TF0 = 0;
      }
   }
   CR = 0;                                // Stop PCA0

   // read 32-bit Timer0 value

   temp.UInt[0] = T0_high;
   temp.Char[2] = TH0;
   temp.Char[3] = TL0;

   INTCLK = temp.Long;                    // INTCLK = Timer0
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -