Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
c
//----------------------------------------------------------------------------// Copyright 2005 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program measures the voltage on an external ADC input and prints the
// result to a terminal window via the UART.
//
// The system is clocked using the internal 24.5MHz oscillator multiplied
// up to 49MHz by the on-chip PLL. Results are printed to the UART from a loop
// with the rate set by a delay based on Timer 2. This loop periodically reads
// the ADC value from a global variable, Result.
//
// The ADC makes repeated measurements at a rate determined by
SAMPLE_RATE using
// Timer 3. The end of each ADC conversion initiates an interrupt which calls an
// averaging function. <INT_DEC> samples are averaged then the Result value
updated.
//
// For each power of 4 of <INT_DEC>, you gain 1 bit of effective resolution.
// For example, <INT_DEC> = 256 gain you 4 bits of resolution: 4^4 = 256.
//
// The ADC input multiplexer is set for a single-ended input at AIN0.1. The input
// amplifier is set for unity gain so a voltage range of 0 to Vref (2.43V) may
// be measured. Although voltages up to Vdd may be applied without damaging
the
|
8 o| AGND ----|
//
o| VREF ----|<-|
//
o| AIN0.1 | |
//
o|
//
o|
//
o|
//
o|
//
1 o|
//
--------
//---------//
// How To Test:
//
// 1) Download code to a 'F12x device that is connected to a UART transceiver
// 2) Connect serial cable from the transceiver to a PC
// 3) On the PC, open HyperTerminal (or any other terminal program) and connect
//
//
// FID:
12X000022
// Target:
C8051F12x
// Tool chain:
//
-19-May-06
//
//----------------------------------------------------------------------------// Includes
//-----------------------------------------------------------------------------
#include <c8051f120.h>
// SFR declarations
#include <stdio.h>
sfr16 ADC0
= 0xbe;
// ADC0 data
sfr16 RCAP2
= 0xca;
// Timer2 capture/reload
sfr16 RCAP3
= 0xca;
// Timer3 capture/reload
sfr16 TMR2
= 0xcc;
// Timer2
sfr16 TMR3
= 0xcc;
// Timer3
sfr16 RCAP4
= 0xca;
// Timer4 capture/reload
sfr16 TMR4
= 0xcc;
// Timer4
sfr16 DAC0
= 0xd2;
// DAC0 data
sfr16 DAC1
= 0xd2;
// DAC1 data
#define BAUDRATE
#define SYSCLK
115200
49000000
256
#define SAR_CLK
2500000
// Sample frequency in Hz
// Integrate and decimate ratio
// Desired SAR clock speed
// LED='1' means ON
// SW1='0' means switch pressed
long Result;
WDTCN = 0xde;
// Measured voltage in mV
WDTCN = 0xad;
OSCILLATOR_Init ();
PORT_Init ();
// UART1_Init ();
// Initialize oscillator
// Initialize crossbar and GPIO
// Initialize UART1
TIMER4_Init(SYSCLK/SAMPLE_RATE_DAC);
ADC0_Init ();
// sample rate
// Init ADC
SFRPAGE = ADC0_PAGE;
AD0EN = 1;
// Enable ADC
EA = 1;
while (1)
{
EA = 0;
// Disable interrupts
Vref (mV)
(2^12)-1 (bits)
EA = 1;
// Re-enable interrupts
// SFRPAGE = UART1_PAGE;
//SFRPAGE = CONFIG_PAGE;
//LED = ~SW1;
SFRPAGE = DAC0_PAGE;
Wait_MS(SAMPLE_DELAY);
// another sample
}
}
//----------------------------------------------------------------------------// OSCILLATOR_Init
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters : None
//
// This function initializes the system clock to use the internal oscillator
// at 24.5 MHz multiplied by two using the PLL.
//
//-----------------------------------------------------------------------------
// Software timer
SFRPAGE = CONFIG_PAGE;
OSCICN = 0x83;
CLKSEL = 0x00;
//Turn on the PLL and increase the system clock by a factor of M/N = 2
SFRPAGE = CONFIG_PAGE;
PLL0CN = 0x00;
SFRPAGE = LEGACY_PAGE;
FLSCL = 0x10;
SFRPAGE = CONFIG_PAGE;
PLL0CN |= 0x01;
PLL0DIV = 0x01;
PLL0FLT = 0x01;
PLL0MUL = 0x02;
// Multiply SYSCLK by M (M = 2)
CLKSEL = 0x02;
SFRPAGE = SFRPAGE_SAVE;
//----------------------------------------------------------------------------// PORT_Init
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.4 digital push-pull
UART TX
UART RX
LED
Analog input (no configuration necessary)
SFRPAGE = CONFIG_PAGE;
XBR0
= 0x00;
XBR1
= 0x00;
XBR2
= 0x44;
P0MDOUT |= 0x01;
P1MDOUT |= 0x40;
SFRPAGE = SFRPAGE_SAVE;
//----------------------------------------------------------------------------// UART1_Init
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters : None
//
// Configure the UART1 using Timer1, for <baudrate> and 8-N-1.
//
//----------------------------------------------------------------------------//void UART1_Init (void)
//{
//char SFRPAGE_SAVE = SFRPAGE;
// SFRPAGE = UART1_PAGE;
//SCON1 = 0x10;
//SFRPAGE = TIMER01_PAGE;
//TMOD &= ~0xF0;
//TMOD |= 0x20;
// if (SYSCLK/BAUDRATE/2/256 < 1) {
// TH1 = -(SYSCLK/BAUDRATE/2);
// CKCON |= 0x10;
// T1M = 1; SCA1:0 = xx
// T1M = 0; SCA1:0 = 00
//} else {
// TH1 = -(SYSCLK/BAUDRATE/2/48);
//CKCON &= ~0x13;
// CKCON |= 0x02;
// }
//TL1 = TH1;
//TR1 = 1;
// Initialize Timer1
// Start Timer1
// SFRPAGE = UART1_PAGE;
// TI1 = 1;
// SFRPAGE = SFRPAGE_SAVE;
//}
//----------------------------------------------------------------------------// ADC0_Init
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters : None
//
// Configure ADC0 to use Timer3 overflows as conversion source, to
// generate an interrupt on conversion complete, and to use right-justified
// output mode. Enables ADC end of conversion interrupt. Leaves ADC disabled.
//
//----------------------------------------------------------------------------void ADC0_Init (void)
{
char SFRPAGE_SAVE = SFRPAGE;
SFRPAGE = ADC0_PAGE;
ADC0CN = 0x04;
REF0CN = 0x07;
AMX0CF = 0x00;
AMX0SL = 0x01;
EIE2 |= 0x02;
SFRPAGE = SFRPAGE_SAVE;
//----------------------------------------------------------------------------// TIMER3_Init
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters :
// 1) int counts - calculated Timer overflow rate
//
//
// Configure Timer3 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
//----------------------------------------------------------------------------void TIMER3_Init (int counts)
{
char SFRPAGE_SAVE = SFRPAGE;
SFRPAGE = TMR3_PAGE;
TMR3CN = 0x00;
TMR3CF = 0x08;
RCAP3 = -counts;
TMR3
= RCAP3;
= 1;
SFRPAGE = SFRPAGE_SAVE;
//----------------------------------------------------------------------------// ADC0_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>.
//
// Integrate/decimate counter
// ADC samples
AD0INT = 0;
accumulator += ADC0;
// total
int_dec--;
if (int_dec == 0)
{
int_dec = INT_DEC;
// Reset counter
// Reset accumulator
}
}
//----------------------------------------------------------------------------// Wait_MS
//----------------------------------------------------------------------------//
// Return Value : None
// Parameters:
// 1) unsigned int ms - number of milliseconds of delay
//
//
// This routine inserts a delay of <ms> milliseconds.
//
//----------------------------------------------------------------------------void Wait_MS(unsigned int ms)
{
char SFRPAGE_SAVE = SFRPAGE;
SFRPAGE = TMR2_PAGE;
TMR2CN = 0x00;
TMR2CF = 0x00;
RCAP2 = -(SYSCLK/1000/12);
TMR2 = RCAP2;
ET2 = 0;
TR2 = 1;
// Start Timer 2
while(ms)
{
TF2 = 0;
while(!TF2);
ms--;
// Decrement ms
TR2 = 0;
// Stop Timer 2
SFRPAGE = SFRPAGE_SAVE;
// Restore SFRPAGE
void DAC0_Init(void){
SFRPAGE = DAC0_PAGE;
DAC0CN = 0x94;
SFRPAGE = LEGACY_PAGE;
REF0CN |= 0x03;
SFRPAGE = SFRPAGE_SAVE;
SFRPAGE = TMR4_PAGE;
TMR4CN = 0x00;
TMR4CF = 0x08;
RCAP4 = -counts;
TMR4 = RCAP4;
EIE2 |= 0x04;
TR4 = 1;
SFRPAGE = SFRPAGE_SAVE;
void Set_DACs(void)
{
char SFRPAGE_SAVE = SFRPAGE;
// phase_acc += PHASE_ADD;
// SIN_temp = SINE_TABLE[index];
//index += 64;
// COS_temp = SINE_TABLE[index];
// Add a DC bias to change the the rails from a bipolar (-32768 to 32767)
// to unipolar (0 to 65535)
// Note: the XOR with 0x8000 translates the bipolar quantity into
// a unipolar quantity.
SFRPAGE = DAC0_PAGE;
DAC0 = 15*Result;
//SFRPAGE = DAC1_PAGE;
// Write to DAC0
SFRPAGE = SFRPAGE_SAVE;
// Write to DAC1