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

📄 osc_rtc_cal1.c

📁 C8051F系列C源码方便对此类单片机有兴趣的同志学习之用
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// OSC_RTC_Cal1.c
//-----------------------------------------------------------------------------
// Copyright 2002 Cygnal Integrated Products, Inc.
//
// AUTH: BW
// DATE: 01 MAR 02
//
// This program shows an example of how an external crystal oscillator
// can be used to measure the internal oscillator frequency to a sufficient
// degree to enable UART operation (better than +/- 2.5%).
//
// In this example, a 32.768kHz watch crystal (with associated loading
// capacitors) is connected between XTAL1 and XTAL2.  The PCA counter is
// used as a generic 16-bit counter that uses EXTCLK / 8 as its time base.
// We preload it to generate an overflow in 8 counts.  Timer0 is configured
// as a 16-bit counter that is set to count SYSCLKs.  The internal oscillator
// is configured to its highest setting, and provides the system clock source.
//
// The number of 16 MHz clock cycles that occur in 4096 cycles of
// EXTCLK / 8 when EXTCLK = 32.768kHz is  16,000,000.  It is calculated as 
// follows: 16MHz / 32.768kHz * 8 * 8 * 512 = 31,250 * 512 = 16,000,000. 
//
// The measurement algorithm used in SYSCLK_Measure () counts the total number
// of system clocks in 4096 periods of EXTCLK / 8 (1 full second) and maintains
// overflow counters using Timer0. The result is given in MHz.
//
// The system clock frequency is then stored in a global variable SYSCLK.  The
// target UART baud rate is stored in a global constant BAUDRATE.
//
// A set of RTC values for seconds, minutes, hours, and days are also
// maintained by the interrupt handler for Timer 3, which is configured
// to use EXTCLK / 8 as its time base and to reload every 4096 counts.
// This generates an interrupt once every second.
//
// 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 SYSCLK       22118400          // SYSCLK frequency in Hz
#define BAUDRATE     19200             // 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 Timer3_Init (void);
void SYSCLK_Measure (void);

void Timer3_ISR (void);

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

long SYSCLK;                           // holds SYSCLK frequency in Hz
unsigned char SECONDS;                 // seconds counter
unsigned char MINUTES;                 // minutes counter
unsigned char HOURS;                   // hours counter
unsigned int DAYS;                     // days counter

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

void main (void) {

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

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

   Timer3_Init ();                     // initialize Timer 3 for RTC mode

   EA = 1;                             // enable global interrupts

   SYSCLK_Measure ();                 // measure internal oscillator and
                                       // update SYSCLK variable

   UART0_Init ();                      // initialize UART0

   printf ("\nSYSCLK = %ld Hz\n\n", SYSCLK);
 
   while (1) {

      OSCICN = 0x07;                   // switch to fast internal osc

      LED = 1;                         // turn LED on

      printf ("%u Days, %02u:%02u:%02u\n", DAYS, (unsigned) HOURS,
              (unsigned) MINUTES, (unsigned) SECONDS);

      while (TI0 == 0);                // wait for end of transmission

      OSCICN = 0x08;                   // switch to EXTOSC

      LED = 0;                         // turn LED off

      PCON |= 0x01;                    // go into IDLE mode (CPU will be
                                       // awakened by the next interrupt,
                                       // and will re-print the RTC
                                       // values).
   }
}

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

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use a low-frequency crystal
// as its clock source.
//
void SYSCLK_Init (void)
{
   int i;                              // delay counter
   int current, last;                  // used in osc. stabilization check
   int tolerance_count;

   OSCXCN = 0x60;                      // start external oscillator with
                                       // low-frequency crystal

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

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

   OSCICN = 0x07;                      // select internal oscillator at its
                                       // fastest setting as the system
                                       // clock source

   // low-frequency crystal stabilization wait routine
   // Here we measure the number of system clocks in 8 EXTCLK / 8 periods.
   // We compare successive measurements.  When we obtain 1000 measurements
   // in a row that are all within 20 system clocks of each other, the
   // routine will exit.  This condition will only occur once the crystal
   // oscillator has fully stabilized at its resonant frequency.  
   // 
   // Note that this can take several seconds.

   // init PCA0
   PCA0CN = 0x00;                         // Stop counter; clear all flags
   PCA0MD = 0x0b;                         // PCA counts in IDLE mode;
                                          // EXTCLK / 8 is time base;

⌨️ 快捷键说明

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