📄 data_logger_rtc.c
字号:
//-----------------------------------------------------------------------------
// Data_Logger_RTC.c
//-----------------------------------------------------------------------------
// Copyright 2002 Cygnal Integrated Products, Inc.
//
// AUTH: FB
// DATE: 30 SEP 02
//
//
// This application uses a 22.1184 MHz crystal oscillator to implement a
// software real-time clock (RTC). PCA Module 0, configured to count Timer 0
// overflows in software timer mode, generates an interrupt every second.
// The interrupt handler records the current time and device temperature
// in a non-volatile log in FLASH.
//
// With SYSCLK at 49.7664 MHZ, Timer 0 in mode 2 overflows exactly 4050 times
// every second when clocked by SYSCLK/48. PCA0, clocked by Timer 0 overflows,
// is programmed to generate an interrupt every 4050 Timer 0 overflows,
// or once every second.
//
// The 112,640 byte log cycles through all 4 code banks recording time and
// temperature. Each data record is 8 bytes long. The log is capable of storing
// 14080 records over a time period of 3.9 hours. Once the log is full, it
// continues logging at the beginning of log, erasing the FLASH page with
// the oldest data as it progresses.
//
// When this code is built, the linker generates two multiple call to segments
// warnings. These warnings are generated because the FLASH support routines
// are called from the main routine and from interrupts. These warnings have
// been accounted for in the code by disabling interrupts before calling any
// FLASH support routines.
//
//
// Target: C8051F12x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f120.h> // SFR declarations
#include <stdio.h> // printf() and getchar()
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F12x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
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 RCAP3 = 0xca; // Timer3 capture/reload
sfr16 RCAP4 = 0xca; // Timer4 capture/reload
sfr16 TMR2 = 0xcc; // Timer2
sfr16 TMR3 = 0xcc; // Timer3
sfr16 TMR4 = 0xcc; // Timer4
sfr16 DAC0 = 0xd2; // DAC0 data
sfr16 DAC1 = 0xd2; // DAC1 data
sfr16 PCA0CP5 = 0xe1; // PCA0 Module 5 capture
sfr16 PCA0CP2 = 0xe9; // PCA0 Module 2 capture
sfr16 PCA0CP3 = 0xeb; // PCA0 Module 3 capture
sfr16 PCA0CP4 = 0xed; // PCA0 Module 4 capture
sfr16 PCA0 = 0xf9; // PCA0 counter
sfr16 PCA0CP0 = 0xfb; // PCA0 Module 0 capture
sfr16 PCA0CP1 = 0xfd; // PCA0 Module 1 capture
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
typedef union UInt { // Byte addressable unsigned int
unsigned int Int;
unsigned char Char[2];
} UInt;
typedef union Long { // Byte addressable long
long Long;
unsigned int Int[2];
unsigned char Char[4];
} Long;
typedef union ULong { // Byte addressable unsigned long
unsigned long ULong;
unsigned int Int[2];
unsigned char Char[4];
} ULong;
typedef struct Record { // LOG record structure
char start;
unsigned int hours;
unsigned char minutes;
unsigned char seconds;
unsigned int ADC_result;
char end;
} Record;
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define TRUE 1
#define FALSE 0
#define EXTCLK 22118400 // External oscillator frequency in Hz
#define SYSCLK 49766400 // Output of PLL derived from
// (EXTCLK*9/4)
#define BAUDRATE 115200 // Baud rate of UART in bps
// Note: The minimum standard baud rate
// supported by the UART0_Init routine
// in this file is 19,200 bps when
// SYSCLK = 49.76MHz.
#define SAMPLERATE 2000 // The ADC sampling rate in Hz
sbit LED = P1^6; // LED='1' means ON
sbit SW2 = P3^7; // SW2='0' means switch pressed
#define LOG_START 0x04000L // Starting address of LOG
#define LOG_END 0x1F800L // Last address in LOG + 1
#define RECORD_LEN 8 // Record length in bytes
#define START_OF_RECORD ':' // Start of Record symbol
#define FLASH_PAGESIZE 1024 // Number of bytes in each FLASH page
#define COBANK 0xF0 // Bit mask for the high nibble of PSBANK
#define COBANK0 0x00 // These macros define the bit mask values
#define COBANK1 0x10 // for the PSBANK register used for
#define COBANK2 0x20 // selecting COBANK. COBANK should always
#define COBANK3 0x30 // be cleared then OR-Equaled (|=) with
// the proper bit mask to avoid changing
// the other bits in the PSBANK register
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
unsigned char SECONDS = 0; // global RTC seconds counter
unsigned char MINUTES = 0; // global RTC minutes counter
unsigned int HOURS = 0; // global RTC hours counter
unsigned int ADC_RESULT = 0; // holds the oversampled and averaged
// result from ADC0
bit LOG_FLAG = 0; // this flag is used to enable
// and disable logging but does
// not affect the real-time clock
bit LOG_ERASED = 0; // this flag indicates that the
// LOG has been erased.
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void main(void);
void RTC_update(void);
void print_menu(void);
// initialization routines
void SYSCLK_Init(void);
void PORT_Init(void);
void UART0_Init (void);
void ADC0_Init (void);
void Timer3_Init(int counts);
void RTC_Init (void);
void PCA0_ISR (void);
// FLASH support routines
void FLASH_PageErase (unsigned long addr);
void FLASH_Write (unsigned long dest, char* src, unsigned int numbytes);
void FLASH_ByteWrite (unsigned long dest, char dat);
void FLASH_Read ( char* dest, unsigned long src, unsigned int numbytes);
unsigned char FLASH_ByteRead (unsigned long addr);
// LOG support routines
void print_time(void);
void LOG_erase(void);
unsigned long find_current_record(void);
void LOG_print(char all_at_once);
void LOG_update(void);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
#define input_str_len 4 // buffer to hold characters entered
char input_str[input_str_len]; // at the command prompt
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
PORT_Init (); // initialize crossbar and GPIO
SYSCLK_Init (); // initialize oscillator
UART0_Init (); // initialize UART0
ADC0_Init(); // initialize ADC0
RTC_Init (); // initializes Timer0 and the PCA
Timer3_Init(SYSCLK/SAMPLERATE); // initialize Timer3 to overflow
// and generate interrupts at
// <SAMPLERATE> Hz
// to implement a real-time clock
EA = 1; // enable global interrupts
print_menu(); // print the command menu
while (1){
SFRPAGE = UART0_PAGE;
printf("\nEnter a command > ");
gets(input_str, input_str_len);
switch ( input_str[0] ){
case '1': LOG_FLAG = 1;
SFRPAGE = UART0_PAGE;
printf("\nLogging has now started.\n");
break;
case '2': LOG_FLAG = 0;
SFRPAGE = UART0_PAGE;
printf("\nLogging has now stopped.\n");
break;
case '3': LOG_FLAG = 0;
LOG_erase();
SFRPAGE = UART0_PAGE;
printf("\nThe log has been erased and logging is stopped.\n");
break;
case '4': LOG_print(FALSE);
print_menu();
break;
case '5': LOG_print(TRUE);
print_menu();
break;
case '6': print_time();
break;
case '?': print_menu();
break;
default: printf("\n*** Unknown Command.\n");
break;
}
} // end while
}
//-----------------------------------------------------------------------------
// RTC_update
//-----------------------------------------------------------------------------
//
//
void RTC_update(void)
{
SECONDS++;
if (SECONDS == 60) {
SECONDS = 0;
MINUTES++;
if (MINUTES == 60) {
MINUTES = 0;
HOURS++;
}
}
}
//-----------------------------------------------------------------------------
// FLASH Support Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FLASH_PageErase
//-----------------------------------------------------------------------------
//
// This function erases the FLASH page containing <addr>.
//
void FLASH_PageErase (unsigned long addr)
{
char SFRPAGE_SAVE = SFRPAGE; // Preserve current SFR page
char PSBANK_SAVE = PSBANK; // Preserve current code bank
bit EA_SAVE = EA; // Preserve interrupt state
ULong temp_addr; // Temporary ULong
char xdata * idata pwrite; // FLASH write/erase pointer
temp_addr.ULong = addr; // copy <addr> to a byte addressable
// unsigned long
// Extract address information from <addr>
pwrite = (char xdata *) temp_addr.Int[1];
// Extract code bank information from <addr>
PSBANK &= ~COBANK; // Clear the COBANK bits
if( temp_addr.Char[1] == 0x00){ // If the address is less than
// 0x10000, the Common area and
PSBANK |= COBANK1; // Bank1 provide a 64KB linear
// address space
} else { // Else, Bank2 and Bank3 provide
// a 64KB linear address space
if (temp_addr.Char[2] & 0x80){ // If bit 15 of the address is
// a '1', then the operation should
PSBANK |= COBANK3; // target Bank3, else target Bank2
} else {
PSBANK |= COBANK2;
temp_addr.Char[2] |= 0x80;
pwrite = (char xdata *) temp_addr.Int[1];
}
}
SFRPAGE = LEGACY_PAGE;
EA = 0; // Disable interrupts
FLSCL |= 0x01; // Enable FLASH writes/erases
PSCTL = 0x03; // MOVX erases FLASH page
*pwrite = 0; // Initiate FLASH page erase
FLSCL &= ~0x01; // Disable FLASH writes/erases
PSCTL = 0x00; // MOVX targets XRAM
EA = EA_SAVE; // Restore interrupt state
PSBANK = PSBANK_SAVE; // Restore current code bank
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// FLASH_Write
//-----------------------------------------------------------------------------
//
// This routine copies <numbytes> from <src> to the FLASH addressed by <dest>.
//
void FLASH_Write (unsigned long dest, char* src, unsigned int numbytes)
{
unsigned int i; // Software Counter
for (i = 0; i < numbytes; i++) {
FLASH_ByteWrite( dest++, *src++);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -