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

📄 data_logger_rtc.c

📁 C8051F系列CPU
💻 C
📖 第 1 页 / 共 3 页
字号:
// LOG_update
//-----------------------------------------------------------------------------
//
//
void LOG_update(void)
{
   bit EA_SAVE = EA;                 // Preserve interrupt state
   Record temp_record;               // local LOG record structure
   
   static unsigned long pWrite = LOG_START; 
                                     // pointer used to write to the LOG 
   bit record_erased;                // temporary flag
   unsigned int i;                   // temporary integer
   
   // record the time and ADC reading in the LOG if logging is enabled
   if(LOG_FLAG){
      
      if(LOG_ERASED){
         pWrite = LOG_START;
         LOG_ERASED = 0;   
   
      } else {
         
         // find the current record if the record at pWrite is not erased
         record_erased = 1;
         for(i = 0; i < RECORD_LEN; i++){
            EA = 0;   
            if( FLASH_ByteRead(pWrite+i) != 0xFF ){
               record_erased = 0;
            } 
            EA = EA_SAVE;
         }
         if(!record_erased){
            pWrite = find_current_record();
         }      


         // build the temporary record
         temp_record.start = START_OF_RECORD;
         temp_record.hours = HOURS;
         temp_record.minutes = MINUTES;
         temp_record.seconds = SECONDS;
         temp_record.ADC_result = ADC_RESULT;
      
         // write the temporary record to FLASH
         EA = 0;   
         FLASH_Write( pWrite, (char*) &temp_record, RECORD_LEN);     
         EA = EA_SAVE;
         
         // increment record pointer
         pWrite += RECORD_LEN;      
      
         // if <pWrite> is past the end of the LOG, reset to the top
         if(pWrite >= LOG_END){
            pWrite = LOG_START;
         }      
      } // end else     
   } // end if(LOG_FLAG)
   
}




//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an external 22.1184 MHz 
// crystal oscillator multiplied by a factor of 9/4 using the PLL as its 
// clock source. The resulting frequency is 22.1184 MHz * 9/4 = 49.7664 MHz
//
void SYSCLK_Init (void)
{
   int i;                           // delay counter
   
   char SFRPAGE_SAVE = SFRPAGE;     // Save Current SFR page

   SFRPAGE = CONFIG_PAGE;           // set SFR page

   OSCXCN = 0x67;                   // start external oscillator with
                                    // 22.1184MHz crystal

   for (i=0; i < 256; i++) ;        // Wait for osc. to start up
   
   while (!(OSCXCN & 0x80)) ;       // Wait for crystal osc. to settle

   CLKSEL = 0x01;                   // Select the external osc. as
                                    // the SYSCLK source

   OSCICN = 0x00;                   // Disable the internal osc.
   
   //Turn on the PLL and increase the system clock by a factor of M/N = 9/4
   SFRPAGE = CONFIG_PAGE;
   
   PLL0CN  = 0x04;                  // Set PLL source as external osc.
   SFRPAGE = LEGACY_PAGE;
   FLSCL   = 0x10;                  // Set FLASH read time for 50MHz clk 
                                    // or less 
   SFRPAGE = CONFIG_PAGE;
   PLL0CN |= 0x01;                  // Enable Power to PLL
   PLL0DIV = 0x04;                  // Set Pre-divide value to N (N = 4)
   PLL0FLT = 0x01;                  // Set the PLL filter register for 
                                    // a reference clock from 19 - 30 MHz
                                    // and an output clock from 45 - 80 MHz 
   PLL0MUL = 0x09;                  // Multiply SYSCLK by M (M = 9)
   
   for (i=0; i < 256; i++) ;        // Wait at least 5us
   PLL0CN  |= 0x02;                 // Enable the PLL
   while(!(PLL0CN & 0x10));         // Wait until PLL frequency is locked
   CLKSEL  = 0x02;                  // Select PLL as SYSCLK source

   SFRPAGE = SFRPAGE_SAVE;          // Restore SFR page
}


//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// This routine configures the Crossbar and GPIO ports.
//
void PORT_Init (void)
{
   char SFRPAGE_SAVE = SFRPAGE;     // Save Current SFR page
      
   SFRPAGE = CONFIG_PAGE;           // set SFR page

   XBR0     = 0x04;                 // Enable UART0
   XBR1     = 0x00;
   XBR2     = 0x40;                 // Enable crossbar and weak pull-up
                                    

   P0MDOUT |= 0x01;                 // Set TX0 pin to push-pull
   P1MDOUT |= 0x40;                 // Set P1.6(LED) to push-pull
   
   SFRPAGE = SFRPAGE_SAVE;          // Restore SFR page
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1. In order to
// increase the clocking flexibility of Timer0, Timer1 is configured to count
// SYSCLKs. 
// 
// To use this routine SYSCLK/BAUDRATE/16 must be less than 256. For example,
// if SYSCLK = 50 MHz, the lowest standard baud rate supported by this
// routine is 19,200 bps. 
//
void UART0_Init (void)
{
   char SFRPAGE_SAVE = SFRPAGE;     // Save Current SFR page
   
   SFRPAGE = UART0_PAGE;

   SCON0  = 0x50;                   // SCON0: mode 0, 8-bit UART, enable RX
   SSTA0  = 0x10;                   // Timer 1 generates UART0 baud rate and
                                    // UART0 baud rate divide by two disabled
   SFRPAGE = TIMER01_PAGE;
   TMOD   &= ~0xF0;                  
   TMOD   |=  0x20;                 // TMOD: timer 1, mode 2, 8-bit reload
   
   TH1 = -(SYSCLK/BAUDRATE/16);     // Set the Timer1 reload value
                                    // When using a low baud rate, this equation
                                    // should be checked to ensure that the
                                    // reload value will fit in 8-bits.
                                                           
   CKCON |= 0x10;                   // T1M = 1; SCA1:0 = xx
   

   TL1 = TH1;                       // initialize Timer1
   TR1 = 1;                         // start Timer1  
   
   SFRPAGE = UART0_PAGE;
   TI0 = 1;                         // Indicate TX0 ready
   
   SFRPAGE = SFRPAGE_SAVE;          // Restore SFR page
}

//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Configure ADC0 to start conversions on Timer3 Overflows and to
// use left-justified output mode. 
//
void ADC0_Init (void)
{
   char SFRPAGE_SAVE = SFRPAGE;     // Save Current SFR page
   
   SFRPAGE = ADC0_PAGE;

   ADC0CN = 0x85;                   // ADC0 enabled; normal tracking
                                    // mode; ADC0 conversions are initiated
                                    // on Timer3 overflows; ADC0 data is
                                    // left-justified

   REF0CN = 0x07;                   // enable temp sensor, on-chip VREF,
                                    // and VREF output buffer
   AMX0SL = 0x0F;                   // Select TEMP sens as ADC mux output

   ADC0CF = ((SYSCLK/2500000) << 3);// ADC conversion clock = 2.5MHz

   ADC0CF |= 0x01;                  // PGA gain = 2

   EIE2 |= 0x02;                    // Enable ADC0 End-of-conversion 
                                    // interrupts
   
   SFRPAGE = SFRPAGE_SAVE;          // Restore SFR page
}

//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
// This routine initializes Timer3 in auto-reload mode to overflow
// at intervals specified in <counts>.
//
void Timer3_Init (int counts)
{
   SFRPAGE = TMR3_PAGE;
   
   TMR3CN = 0;                       // STOP timer; set to auto-reload mode
   TMR3CF = 0x08;                    // Timer3 counts SYSCLKs
   RCAP3 = -counts;                  // set reload value
   TMR3 = RCAP3;
   TR3 = 1;                          // start Timer3
      
}

//-----------------------------------------------------------------------------
// RTC_Init
//-----------------------------------------------------------------------------
//
// This Routine initializes Timer0 and PCA0 to implement a real-time clock.
// Assuming <SYSCLK> is generated from a 22.1184 crystal oscillator, Timer0
// overflows exactly 1800 times per second when configured as an 8-bit timer 
// that uses <SYSCLK>/48 as its timebase. PCA0 is configured to count 
// Timer0 overflows and interrupt every 1800 Timer0 overflows, or every second.
// The PCA0 ISR updates a set of global RTC counters for seconds, minutes, hours,
// and days. 
//
void RTC_Init(void)
{
   char SFRPAGE_SAVE = SFRPAGE;     // Save Current SFR page

   SFRPAGE = TIMER01_PAGE;

   // configure Timer0 in Mode2: 8-bit Timer with Auto-Reload
   TMOD &= ~0x0F;                   // Clear Timer0 bits
   TMOD |= 0x02;                    // Mode2 Auto-Reload
   
   // configure Timer0 timebase to <SYSCLK>/48
   CKCON &= ~0x0F;                  // Clear bits
   CKCON |= 0x02;                   // Set Timer0 timebase  
   
   // configure PCA0 to count Timer0 overflows 
   PCA0MD = 0x04;
   
   // configure capture/compare module 0 to generate an interrupt when
   // the value of PCA0 reaches 4050 (0x0FD2)  
   PCA0CP0 = 4050;                  // Set the value to match
     
   PCA0CPM0 &= ~0xFF;               // Clear bits
   PCA0CPM0 |= 0x49;                // Generate an interrupt when the 
                                    // PCA0 value matches PCA0CP0

   EIE1 |= 0x08;                    // Enable PCA0 interrupts
   
     
   TR0 = 1;                         // Start Timer0
   PCA0CN |= 0x40;                  // Enable PCA0

   SFRPAGE = SFRPAGE_SAVE;          // Restore SFR page
}

//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
//
//
void PCA0_ISR (void) interrupt 9
{
   
  if (CCF0) {
      CCF0 = 0;                         // clear Module0 capture/compare flag
      
      PCA0 = 0x00;                      // clear the PCA counter
      RTC_update();                     // update RTC variables
      LOG_update();                     // update LOG if logging is enabled

  } else 
 
  if (CCF1) {
      CCF1 = 0;                         // clear Module1 capture/compare flag
  } else

  if (CCF2) {
      CCF2 = 0;                         // clear Module2 capture/compare flag
  } else

  if (CCF3) {
      CCF3 = 0;                         // clear Module3 capture/compare flag
  } else

  if (CCF4) {
      CCF4 = 0;                         // clear Module4 capture/compare flag
  } else
   
  if (CCF5) {
      CCF5 = 0;                         // clear Module5 capture/compare flag
  } else
   
  if (CF) {
      CF = 0;                           // clear PCA counter overflow flag
  }
  
}

//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// This ISR is called on the end of an ADC0 conversion.
//
void ADC0_ISR (void) interrupt 15 
{
 
   static Long result = {0};              // byte addressable long variable
	int i;
	bit EA_SAVE = EA;
   //accumulate 256 temperature samples
   result.Long += ADC0;
   i++;
   
   if( i == 256 ) {

      i = 0;
			
   	// take the average (Divide by 256 = shift right by 8)
   	// Do this operation "result.Long >>= 8;" (170 SYSCLK cycles) using
      // three MOV instructions (9 SYSCLK cycles)
      // Assume Most Significant Byte only contains sign information
   
      result.Char[3] = result.Char[2];
      result.Char[2] = result.Char[1];
      result.Char[1] = result.Char[0];
      
      // update global <ADC_RESULT>
      ADC_RESULT = result.Int[1];
   }

}

⌨️ 快捷键说明

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