?? temp_3.c
字號:
//-----------------------------------------------------------------------------
// Temp_3.c
//-----------------------------------------------------------------------------
// Copyright (C) 2004 Silicon Laboratories, Inc.
//
// AUTH: BW
// DATE: 24 JUN 02
//
// This program prints the C8051F30x die temperature out the hardware
// UART at 9600bps. Uses the calibrated internal 24.5MHz oscillator as the
// system clock source.
//
// The ADC is configured to look at the on-chip temp sensor. The sampling
// rate of the ADC is determined by the constant <SAMPLE_RATE>, which is given
// in Hz.
//
// The ADC0 End of Conversion Interrupt Handler retrieves the sample
// from the ADC and adds it to a running accumulator. Every <INT_DEC>
// samples, the ADC updates and stores its result in the global variable
// <result>, which contains the accumulated result. The sampling technique of
// adding a set of values and decimating them (posting results every (n)th
// sample) is called 'integrate and dump.' It is easy to implement and
// requires very few resources.
//
// For each power of 4 of <INT_DEC>, you gain 1 bit of effective resolution.
// For example, <INT_DEC> = 4096 gain you 6 bits of resolution: 4^6 = 4096.
//
// Target: C8051F30x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h> // SFR declarations
#include <stdio.h>
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F30x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
sfr16 PCA0CP1 = 0xe9; // PCA0 Module 1 Capture/Compare
sfr16 PCA0CP2 = 0xeb; // PCA0 Module 2 Capture/Compare
sfr16 PCA0 = 0xf9; // PCA0 counter
sfr16 PCA0CP0 = 0xfb; // PCA0 Module 0 Capture/Compare
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 9600 // Baud rate of UART in bps
#define SAMPLE_RATE 100000 // Sample frequency in Hz
#define INT_DEC 4096 // integrate and decimate ratio
sbit LED = P0^2; // LED='1' means ON
sbit SW2 = P0^3; // SW2='0' means switch pressed
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void ADC0_Init (void);
void Timer2_Init (int counts);
void ADC0_ISR (void);
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
long result; // ADC0 decimated value
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void) {
long temperature; // temperature in hundredths of a
// degree C
int temp_int, temp_frac; // integer and fractional portions of
// temperature
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
SYSCLK_Init (); // initialize oscillator
PORT_Init (); // initialize crossbar and GPIO
UART0_Init (); // initialize UART0
Timer2_Init (SYSCLK/SAMPLE_RATE); // initialize Timer2 to overflow at
// sample rate
ADC0_Init (); // init ADC0
AD0EN = 1; // enable ADC0
EA = 1; // Enable global interrupts
while (1) {
EA = 0; // disable interrupts
temperature = result;
EA = 1; // re-enable interrupts
// calculate temperature in hundredths of a degree (14-bit full scale)
temperature = temperature - 8700;
temperature = (temperature * 10000L) / 3277;
temp_int = temperature / 100;
temp_frac = temperature - (temp_int * 100);
printf ("Temperature is %+02d.%02d\n", temp_int, temp_frac);
LED = ~SW2; // LED reflects state of SW2
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
void SYSCLK_Init (void)
{
OSCICN |= 0x03; // configure internal oscillator for
// its maximum frequency}
RSTSRC = 0x04; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 -
// P0.1 -
// P0.2 - LED (push-pull)
// P0.3 - SW2
// P0.4 - UART TX (push-pull)
// P0.5 - UART RX
// P0.6 -
// P0.7 - C2D
//
void PORT_Init (void)
{
XBR0 = 0x0c; // skip LED and Switch in crossbar
// assignments
XBR1 = 0x03; // UART0 TX and RX pins enabled
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P0MDOUT |= 0x14; // enable TX0 and LED as a push-pull
// outputs
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x10; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON |= 0x01; // T1M = 0; SCA1:0 = 01
CKCON &= ~0x12;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON |= 0x02; // T1M = 0; SCA1:0 = 10
CKCON &= ~0x11;
}
TL1 = 0xff; // set Timer1 to overflow immediately
TMOD |= 0x20; // TMOD: timer 1 in 8-bit autoreload
TMOD &= ~0xD0; // mode
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Configure ADC0 to use Timer2 overflows as conversion source, to
// generate an interrupt on conversion complete, and to sense the output of
// the temp sensor. Enables ADC end of conversion interrupt. Leaves ADC
// disabled.
//
void ADC0_Init (void)
{
ADC0CN = 0x02; // ADC0 disabled; normal tracking
// mode; ADC0 conversions are initiated
// on overflow of Timer2;
AMX0SL = 0xf8; // select temp sensor as mux input
ADC0CF = (SYSCLK/6000000) << 3; // ADC conversion clock <= 6MHz
ADC0CF |= 0x02; // PGA gain = 2
REF0CN = 0x0e; // enable temp sensor, VREF = VDD, bias
// generator is on.
EIE1 |= 0x04; // enable ADC0 EOC interrupt
}
//-----------------------------------------------------------------------------
// Timer2_Init
//-----------------------------------------------------------------------------
//
// Configure Timer2 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
void Timer2_Init (int counts)
{
TMR2CN = 0x00; // STOP Timer2; Clear TF2H and TF2L;
// disable low-byte interrupt; disable
// split mode; select internal timebase
CKCON |= 0x20; // Timer2 uses SYSCLK as its timebase
TMR2RL = -counts; // Init reload values
TMR2 = 0xffff; // set to reload immediately
ET2 = 0; // disable Timer2 interrupts
TR2 = 1; // start Timer2
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// ADC0 end-of-conversion ISR
// Here we take the ADC0 sample, add it to a running total <accumulator>, and
// decrement our local decimation counter <int_dec>. When <int_dec> reaches
// zero, we post the decimated result in the global variable <result>.
//
void ADC0_ISR (void) interrupt 8 using 3
{
static unsigned int_dec=INT_DEC; // integrate/decimate counter
// we post a new result when
// int_dec = 0
static long accumulator=0L; // here's where we integrate the
// ADC samples
AD0INT = 0; // clear ADC conversion complete
// indicator
accumulator += ADC0; // read ADC value and add to running
// total
int_dec--; // update decimation counter
if (int_dec == 0) { // if zero, then post result
int_dec = INT_DEC; // reset counter
result = accumulator >> 6;
accumulator = 0L; // reset accumulator
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -