📄 temperature.c
字号:
//*****************************************************************************
//
// File........: Temperature.c
//
// Author(s)...: ATMEL Norway
//
// Target(s)...: ATmega169
//
// Compiler....: IAR EWAAVR 2.27b
//
// Description.: Temperature measurements
//
// Revisions...: 1.0
//
// YYYYMMDD - VER. - COMMENT - SIGN.
//
// 20021015 - 1.0 - Created - LHM
//
//*****************************************************************************
// Include files
#include "Main.h"
#include "Temperature.h"
#include "math.h"
// Global variables
unsigned char ADCresult_calc_cnt = 0; // variable to count number of temperature calcualtions
int ADCresult_average = 0; // integer to keep the ADC results for later averaging
float Temperature; // float to calculate the temperature
/******************************************************************************************
*
* Function name : ADC_init
*
* Returns : None
*
* Parameters : Operation, selects between Single Ended or Differential ADC
*
* Purpose : Initialize the ADC and run a dummy ADC conversion
*
******************************************************************************************/
void ADC_init(unsigned char Operation)
{
SET_POINT = 25; // set SET_POINT to 25 degree Celsius
ADMUX |= Operation; // set the selected opeartion, either Single Ended or Differential
Delay(50); // delay in order for channel selection to settle
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // set ADC prescaler to , 1MHz / 8 = 125kHz
DIDR1 = 0xFF; // disable digital input on PORTF
ADC_conversion(); // run a dummy conversion the first time the ADC is used after a power up
}
/******************************************************************************************
*
* Function name : PWM_init
*
* Returns : None
*
* Parameters : None
*
* Purpose : Initialize the Timer1 with PWM, Phase and Frequency Correct, 10-bit
*
******************************************************************************************/
void PWM_init(void)
{
ICR1H = 0x03; // set the TOP value for the PWM to 0x3FF = 10bit
ICR1L = 0xFF;
OCR1AH = OCR1BH = 0x00;
OCR1AL = OCR1BL = 0xF0; // set a initial value in the OCR1A-register
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0); // set OC1A/B on upcounting, clear on downcounting
TCCR1B = (1<<WGM13) | (1<<CS11); // select Phase and Frequency Corrcet, and set CLK(I/O) / 8 (From prescaler)
}
/******************************************************************************************
*
* Function name : ADC_conversion
*
* Returns : None
*
* Parameters : None
*
* Purpose : Run the ADC conversion
*
******************************************************************************************/
void ADC_conversion(void)
{
int ADC_temp;
int ADCresult = 0;
unsigned char i;
for(i=0;i<8;i++) // do the ADC conversion 8 times for better accuracy
{
ADCSRA |= (1<<ADSC); // do single conversion
while(!(ADCSRA & 0x10)); // wait for conversion done, ADIF flag active
ADC_temp = ADCL; // read out ADCL register
ADC_temp += (ADCH << 8); // read out ADCH register
ADCresult += ADC_temp; // accumulate result (8 samples) for later averaging
}
ADCresult = ADCresult >> 3; // average the 8 samples
ADCresult_calc_cnt++; // increment the counter that keeps track of how many calulations that have been donet
ADCresult_average += ADCresult; // add the ADCresult to the previous measurements
if(ADCresult_calc_cnt >= 32) // if 32 calculations
{
ADCresult_calc_cnt = 0; // clear the counter
ADCresult_average = ADCresult_average >> 5; // find the average ADC result for the last 32 times
Temp_calculation(ADCresult_average); // call the temperature calculation function
ADCresult_average = 0; // clear the ADCresult_average
}
}
/******************************************************************************************
*
* Function name : Temp_calculation
*
* Returns : None
*
* Parameters : The result in the ADCH/L registers
*
* Purpose : Calculate the corresponding temperature in degree Celsius,
* and place the value in SRAM at location 0x4F0 - 0x4FF
*
******************************************************************************************/
void Temp_calculation(int iADC_value)
{
float V_ADC;
if((ADMUX & 0x1F) == SingleEnded) // check if Single_ended operation
V_ADC = (iADC_value * V_ref)/1024; // calculate the voltage over the NTC
else if((ADMUX & 0x1F) == Differential) // check if Differential operation
V_ADC = (iADC_value * V_ref)/512; // calculate the voltage over the NTC
Temperature = (Beta / ((log(V_ADC/(V_ref-V_ADC))/log(__E)) + (Beta/T_amb))) - T_zero; // calculate the temperature
TEMP_HIGHBYTE = Temperature; // store the integer to "TEMP_HIGHBYTE"
Temperature = (Temperature - TEMP_HIGHBYTE); // subtract the the integer from Temperature_average
TEMP_LOWBYTE = (Temperature * 100); // multiply Temperature_average by 100 to get the decimal, and store it to "TEMP_LOWBYTE"
Temperature_regulation(); //call the Temperatur_regulation rutine
}
/******************************************************************************************
*
* Function name : Temperature_regulation
*
* Returns : None
*
* Parameters : None
*
* Purpose : Find the difference between measured and requested temperature. And set
* a proper value in the OCR1A-register for the use of PWM on the Leds.
*
******************************************************************************************/
void Temperature_regulation(void)
{
int Offset_OCR1;
unsigned char PWM_8LSB;
unsigned char PWM_2MSB;
OFFSET = (TEMP_HIGHBYTE - SET_POINT); // find the offset between measured temperature and SET POINT
if( OFFSET & 0x80 ) // if a negative offset
{
OFFSET =~ OFFSET; // 2'nd complement the OFFSET to get a positive value
if(OFFSET > 1) // if the offset is more than 1 degree below the set point
{
TCCR1A &= 0x0F; // disable COM1Ax and COM1Bx
TCCR1A |= 0xC0; // set COM1A1 and COM1A0
PORTB = Heater; // set the Heater as output
}
}
else if( OFFSET ) // if the offset is more than 1 degree above the set point
{
TCCR1A &= 0x0F; // disable COM1Ax and COM1Bx
TCCR1A |= 0x30; // set COM1B1 and COM1B0
PORTB = Cooler; // set the Cooler as output
}
else // else then if OFFSET equals the measured temperature, diable Heating and Cooling
{
TCCR1A &= 0x0F; // disable COM1Ax and COM1Bx
PORTB = (1<<PORTB6) | (1<<PORTB5); // shut down LED5 and LED6 (active low on the STK500)
}
Offset_OCR1 = OFFSET; // copy the OFFSET to the Offset_OCR1A
Offset_OCR1 *= (Offset_OCR1 * 2); // Multiply the offset by itself times two, this is done just to
// fill up the 10 bit in the OCR1A register
if(Offset_OCR1 > 0x03FF) // if the Offset_OCR1A is beyond the maximum value of OCR1A in 10-bit mode
Offset_OCR1 = 0x3FF; // write 0x3FF to it.
PWM_8LSB = Offset_OCR1; // load the 8LSB to PWM_8LSB
Offset_OCR1 >>= 8; // move the value in Offset_OCR1 8 times to the right
PWM_2MSB = Offset_OCR1; // load the 2MSB int
OCR1AH = OCR1BH = PWM_2MSB; // write the high byte of the OCR1A/B registers
OCR1AL = OCR1BL = PWM_8LSB; // write the low byte of the OCR1A/B registers
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -