⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 temperature.c

📁 一个LCD驱动程序
💻 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 + -