📄 data_logger_rtc.c
字号:
// 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 + -