请问如何用sdcc编写一个 temperature sensor?

内核编译和嵌入式产品的设计与开发
回复
wayne_sh09
帖子: 1
注册时间: 2007-07-19 15:32

请问如何用sdcc编写一个 temperature sensor?

#1

帖子 wayne_sh09 » 2007-07-19 15:36

RT 请高手们 能帮忙解答,有个程序能做这个,不过是在keil C的背景下运行 请问如何才能做到在sdcc上运行?

源代码:
//-----------------------------------------------------------------------------
// F330DC_ADC0_TemperatureSensor.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program is used to measure the temperature sensor on an 'F33x
// device. It uses 1-point calibration and stores the offset value
// in Flash memory. The program outputs the temperature with accuracy to
// 100ths of a degree Celsius using the UART.
//
// How To Test:
//
// 1) Change the #define AMBIENT_TEMPERATURE to accurately reflect the
// the temperarture of the testing environment
// 2) Compile and download the code to a ToolStick F330 Daughter Card
// 3) Connect to the ToolStick using ToolStick Terminal using the settings
// defined by <BAUD_RATE>
// 4) Check that the printed temperature is close to the ambient temperature
//
// FID: 33X000032
// Target: ToolStick C8051F330
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Command Line: None
//
//
// Release 1.0
// -Initial Revision (PD/GV/GP)
// -06 AUG 2006
//

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <C8051F330.h> // SFR declarations
#include <stdio.h>

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F33x
//-----------------------------------------------------------------------------

sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
sfr16 ADC0 = 0xbd; // ADC Data Word Register

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
#define TIMER2_RATE 1000 // Timer 2 overflow rate in Hz

//-----------------------------------------------------------------------------
// Temperature Sensor Calibration Parameters
//-----------------------------------------------------------------------------
#define AMBIENT_TEMPERATURE 25 // Ambient Calibration Temperature
// (degC)

#define TEMP_SENSOR_GAIN 2860 // Temp Sensor Gain in (uV / degC)
// Value obtained from datasheet

#define VREF 2430 // ADC Voltage Reference (mV)

#define SOAK_TIME 5 // Soak Time in Seconds


//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

// TEMP_OFFSET allocates two bytes of code memory space in FLASH
// that will be used to store the calibrated temperature value
unsigned int code TEMP_OFFSET = 0xFFFF;

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void ADC0_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void TIMER2_Init (int);

void Print_String (char pstring[]);
void Flash_ByteWrite (unsigned long addr, char byte);

void Wait_Soak_Time (unsigned char soak_time);
void Wait_One_Second (void);
int Get_Temperature (void);
void Calibrate_TempSensor (void);
unsigned int Measure_Temperature (void);

// ISRs defined: None.

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------

void main (void)
{
unsigned int temperature; // Stores last measurement

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
PORT_Init (); // Initialize Port I/O
OSCILLATOR_Init (); // Initialize Oscillator

ADC0_Init (); // Init ADC0
TIMER2_Init (SYSCLK/TIMER2_RATE); // Init Timer 2
UART0_Init ();

AD0EN = 1; // Enable ADC0

if (TEMP_OFFSET == 0xFFFF) // True if first-time to execute
{
Print_String ("Calibrating...\n");
Calibrate_TempSensor (); // Execute calibration sequence
}
else
{
Print_String ("Calibration previously completed\n");
}

while (1)
{
temperature = Get_Temperature ();
Print_String ("Temperature = ");

// This method of printing the temperature is an alternative to using
// printf() and its capabilities

EA = 0;
putchar ((temperature / 1000) + 0x30); // Tens digit
putchar (((temperature / 100) % 10) + 0x30); // Ones digit
putchar ('.');
putchar (((temperature / 10) % 10) + 0x30); // Tenths digit
putchar ((temperature % 10) + 0x30); // Hundredths digit
EA = 1;

Print_String (" degrees C\n");
}
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P0MDIN |= 0x01; // Configure P0.0 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure ADC0 to use ADBUSY as conversion source, and to sense the output
// of the temp sensor. Disables ADC end of conversion interrupt. Leaves ADC
// disabled.
//
//-----------------------------------------------------------------------------

void ADC0_Init (void)
{
ADC0CN = 0x40; // ADC0 disabled; LP tracking
// mode; ADC0 conversions are initiated
// on a write to ADBusy
AMX0P = 0x10; // Temp sensor selected at + input
AMX0N = 0x11; // Single-ended mode

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

ADC0CF &= ~0x04; // Make ADC0 right-justified
REF0CN = 0x0e; // enable temp sensor, VREF = VDD, bias
// generator is on.

EIE1 &= ~0x08; // Disable ADC0 EOC interrupt
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// 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 &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}

//-----------------------------------------------------------------------------
// TIMER2_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int counts - number of milliseconds of delay
// range is postive range of integer: 0 to 32767
//
// 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 |= 0x10; // Timer2 uses SYSCLK as its timebase

TMR2RL = -counts; // Init reload values
TMR2 = TMR2RL; // Init Timer2 with reload value
ET2 = 0; // Disable Timer2 interrupts
TR2 = 1; // Start Timer2
}

//-----------------------------------------------------------------------------
// Support Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Wait_Soak_Time
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) unsigned char soak_time - number of seconds of delay
// range is postive range of integer: 0 to 255
//
// This routine waits for the number of seconds indicated in the constant
// <soak_time>.
//
//-----------------------------------------------------------------------------
void Wait_Soak_Time (unsigned char soak_time)
{
unsigned char i;

for( i = soak_time; i != 0; i--)
{
Wait_One_Second();
Print_String ("Soaking\n");
}
}

//-----------------------------------------------------------------------------
// Wait_One_Second
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine uses Timer2 to insert a delay of approximately one second.
// Timer 2 overflows <TIMER2_RATE> times per second.
//
//-----------------------------------------------------------------------------
void Wait_One_Second (void)
{
unsigned int count;
TF2H = 0; // Clear Timer2 overflow flag
TR2 = 1; // Start Timer2

for (count = TIMER2_RATE; count != 0; count--)
{
while (!TF2H); // Wait for overflow
TF2H = 0; // Clear overflow indicator
}

TR2 = 0; // Stop Timer2
}

//-----------------------------------------------------------------------------
// Calibrate_TempSensor
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine waits for the device to heat to operating temperature, takes an
// ADC measurement, and calculates a temperature. It compares this measured
// value to AMBIENT_TEMPERATURE and calculates an offset, which is stored in a
// Flash memory location for later measurements.
//
//-----------------------------------------------------------------------------
void Calibrate_TempSensor (void)
{

bit EA_state = EA; // Preserves EA state
unsigned long offset_address; // Used to write calibration
// Value into FLASH memory

long temp_offset; // Stores returned value from ADC

Wait_Soak_Time (SOAK_TIME); // Let temperature of device stabilize

temp_offset= (long) Measure_Temperature (); // Read oversampled ADC code


// Now calculate the 0 DEG C offset value using temp_offset, the
// temp sensor gain, and the ambient temperature.

temp_offset = temp_offset - ((long) AMBIENT_TEMPERATURE *
TEMP_SENSOR_GAIN / VREF * 65536 / 1000);


offset_address = &TEMP_OFFSET; // Point to TEMP_OFFSET

Flash_ByteWrite (offset_address, temp_offset >> 8);

offset_address++; // Move to low byte of TEMP_OFFSET in
// Flash to store low byte of offset

Flash_ByteWrite (offset_address, temp_offset);

EA = EA_state; // Restore interrupt state

}

//-----------------------------------------------------------------------------
// Measure_Temperature
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine averages 16383 ADC samples and returns a 16-bit unsigned
// result.
//
//-----------------------------------------------------------------------------
unsigned int Measure_Temperature (void)
{
unsigned i; // Sample counter
unsigned long accumulator = 0L; // Where the ADC samples are integrated

unsigned int currval;

AD0INT = 0; // Clear end-of-conversion indicator
AD0BUSY = 1; // Initiate conversion

// read the ADC value and add to running total
i = 0;
do
{
while (!AD0INT); // Wait for conversion to complete
AD0INT = 0; // Clear end-of-conversion indicator

currval = ADC0; // Store latest ADC conversion
AD0BUSY = 1; // Initiate conversion
accumulator += currval; // Accumulate
i++; // Update counter
} while (i != 16383);

return (unsigned int) (accumulator >> 8); // Obtain a 16-bit result
// (14 + 10 = 24 - 8 = 16) bits
}

//-----------------------------------------------------------------------------
// Get_Temperature
//-----------------------------------------------------------------------------
//
// Return Value : int - returns the temperature in hundredths of degrees
// Parameters : None
//
// This routine averages 16383 ADC samples and returns a 16-bit unsigned
// result.
//
//-----------------------------------------------------------------------------
int Get_Temperature (void)
{
unsigned int ADC_code;
long result;

ADC_code = Measure_Temperature ();

result = ADC_code - TEMP_OFFSET;

// result = result * (VREF / 65536) * (1000 / TEMP_SENSOR_GAIN) * ( 100 )
// the equation below is re-arranged for fixed-point math.

result = result * (long) VREF / 256 * 1000 / TEMP_SENSOR_GAIN * 100 / 256;

return (int) result;
}

//-----------------------------------------------------------------------------
// Support Functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Print_String
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) char pstring[] - null terminated character string
//
// Prints the strings stored in pstring to the UART.
// This function is used instead of printf() because printf() consumes
// a considerable amount of code space.
//
//-----------------------------------------------------------------------------

void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring)
{
putchar(pstring[i++]);
}
}

//-----------------------------------------------------------------------------
// Flash_ByteWrite
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) unsigned int addr - location in Flash to write the byte
// 2) char byte - data to store to Flash
//
// Stores <byte> in address pointed to by <addr>.
// This function was obtained from Application Note 201.
//
//-----------------------------------------------------------------------------

void Flash_ByteWrite (unsigned long addr, char byte)
{
bit EA_SAVE = EA; // Preserve EA
char xdata * data pwrite; // FLASH write pointer

EA = 0; // Disable interrupts

VDM0CN = 0x80; // Enable VDD monitor

RSTSRC = 0x02; // Enable VDD monitor as a reset source

pwrite = (char xdata *) addr; // Point to Flash location

FLKEY = 0xA5; // Key Sequence 1
FLKEY = 0xF1; // Key Sequence 2
PSCTL |= 0x01; // PSWE = 1

VDM0CN = 0x80; // Enable VDD monitor

RSTSRC = 0x02; // Enable VDD monitor as a reset source


*pwrite = byte; // Write the byte


PSCTL &= ~0x01; // PSWE = 0; disable writes

EA = EA_SAVE; // Restore interrupts
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
xuriwuyun
帖子: 47
注册时间: 2008-10-18 15:44

Re: 请问如何用sdcc编写一个 temperature sensor?

#2

帖子 xuriwuyun » 2009-03-09 18:08

这么长怎么看阿
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 请问如何用sdcc编写一个 temperature sensor?

#3

帖子 eexpress » 2009-03-10 9:33

man sdcc
只是一个编译器。
● 鸣学
回复