temprature.c

来自「该源代码为基于AVR单片机的温度加热控制系统的源程序。测温采用的的是热敏电阻」· C语言 代码 · 共 640 行 · 第 1/2 页

C
640
字号
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
?Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : temprature
Version : 1.0
Date    : 2008-4-7
Author  : Freeware, for evaluation and non-commercial use only
Company : ylyw
Comments: 


Chip type           : ATmega8
Program type        : Application
Clock frequency     : 1.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256

设定温度在30~110度之间;实际温度小于20时显示L,大于120时显示H
设定的温度存EEPROM,开机先显示设定的温度约2s左右
*****************************************************/

#include <mega8.h>
#include <delay.h>
#include <math.h>

#define ADC_VREF_TYPE 0x40
#define KG1_UP    PORTD.2                  //设定温度增加键
#define KG2_DOWN  PORTD.3                  //设定温度减少键
#define HEAT_LED  PORTD.4                  //加热指示,高电平点亮
#define HEAT_CTRL PORTC.5                  //加热开关控制,低电平加热 
#define LED_DATA  PORTB                    //LED显示段码数据口
#define LED_S1    PORTD.5                  //LED1显示位选择口,低电平选通
#define LED_S2    PORTD.6                  //LED2显示位选择口,低电平选通
#define LED_S3    PORTD.7                  //LED3显示位选择口,低电平选通
#define set_max 118                        //设定的最大温度值为110度
#define set_min 12                         //设定的最小温度值为30度
#define dis_max 120                        //实际温度显示值最大为120度,大于120显示H
#define dis_min 10                          //实际温度显示值最小为20度,小于20显示L
#define temp_set_dis_time 100              //控制设定温度显示时间长度=主程序运行时间*100   

#define  max_cnt_zkb  100            //控制占空比控制计数器的TOP值  max_cnt_zkb<255
#define  temp_step  10               //开启PID加热的差值门限
#define  temp_kp 9                 //比例控制增益系数
#define  KG1_UP_PD2   PIND.2         //设定温度增加键输入口
#define  KG2_DOWN_PD3  PIND.3        //设定温度减少键输入口
#define  VCC 5.1                     //电源电压(加到测温电路上的电压值)
#define  adc_time  10                 //控制ADC采样的数据的更新延迟时间adc_time * 20 ms

//#define scankey_delaytime 10               //控制主程序查询键盘延迟时间=主程序运行时间*10

// Declare your global variables here 
//flash unsigned char led_segtab[19]={0xB7,0x81,0x3D,0xAD,0x8B,0xAE,0xBE,0x85,
//                                   0xBF,0xAF,0x9F,0xBA,0x38,0xB9,0x3E,0x1E,0x9B,0x32,0x00};
flash unsigned char led_segtab[19]={0x22,0xaf,0xC2,0x83,0x0f,0x13,0x12,0xa7,
                                     0x02,0x03,0x06,0x1a,0xda,0x8a,0x52,0x56,0x0e,0x7a,0xff};
flash unsigned int B_NTC=3950;        //NTC特性参数B值
flash float R25_NTC = 100;             //NTC在25度时的电阻(K)
flash float R_fenya = 20;             //与NTC串联的分压电阻(K)
                                                                     //数码管段码值,其0--F,H,L,空白
//flash unsigned char ledPosition[6]={0xDF,0xBF,0x7F,0X20,0X40,0X80};  //数码管位选与位关
//eeprom unsigned char temprature_set_ = 50 ;                          //存储设定温度,上电时装载此设定温度
unsigned int adc_data;                                               //ADC的原始数据
unsigned char flag_dis;                                              //flag_dis=0显示实际温度,flag_dis=1显示设定温度,开机先显示设定温度,在显示实际温度
float  temprature_real;                                       //实际温度
float  t_n_1,feedback,feedback1;         //PID微分积分项反馈变量
unsigned char temprature_set;                                        //设定温度,初始值为50度
unsigned char counter_soft;                                          //软件计数器,记录设定温度的显示时间:主程序运行时间*100
unsigned char buffer_dis[3];                                         //三位数码管显示段码缓存器 
unsigned char flag_int;                                              //产生了中断的标志
//unsigned char flag_tem;   //不显示小数点标志

unsigned char counter_zhankongbi;    //占空比控制计数器

////////////////////adc////////////////////
float ADC_DAT;          //ADC_DATA必须定义为浮点型,否则ADC_DATA/0x3ff表达式的得不到精确的计算结果
//float Adc_Data_ad[10];       //存10次的采样结果
float Adc_Data_ad1[10];
//float standard_data;       //存十次采样结果的平均值为标准数据
unsigned char n_adc;
//////////////////////////////////////////

///////////////////////////////////////////////////
//unsigned int timer2_counter;//计数T2溢出中断次数
////////////////////////////////////////////////////
//EEPROM 的写操作uiAddress为写入的地址,ucData为写入的数据  

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
while(EECR & (1<<1));              // 查询EEWE等待上一次写操作结束 
EEAR = uiAddress;                  // 设置地址和数据寄存器
EEDR = ucData;
EECR |= (1<<2);                    // 置位EEMWE 
EECR |= (1<<1);                    // 置位EEWE 以启动写操作*
}

//EEPROM 的读操作uiAddress为读取的地址
unsigned char EEPROM_read(unsigned int uiAddress)
{
while(EECR & (1<<1));              // 查询EEWE等待上一次写操作结束
EEAR = uiAddress;                  // 设置地址寄存器
EECR |= (1<<0);                    // 设置EERE 以启动读操作
return EEDR;                       // 自数据寄存器返回数据 
}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
//if (temprature_set < set_max)                   //设定温度值不能高于110度
//{temprature_set += 1;                            //按KG1时设定温度加1
//EEPROM_write(0,temprature_set);                 //保存设定温度值到EEPROM的0单元
//}
flag_dis = 1;                                   //置显示设定温度标志
counter_soft = temp_set_dis_time;               //设置温度显示计数置100
//flag_int = 1;                                   //置产生了中断的标志
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here
//if (temprature_set > set_min)                    //设定温度值不能低于30度                         
//{temprature_set -= 1;                             //按KG2时设定温度减1
//EEPROM_write(0,temprature_set);                  //保存设定温度值到EEPROM的0单元
//}
flag_dis = 1;                                    //置显示设定温度标志
counter_soft = temp_set_dis_time;                //设置温度显示计数置100
//flag_int = 1;                                    //置产生了中断的标志
}

// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
// Read the AD conversion result
adc_data=ADCW;
//adc_data = 494;
}
  
// Read the AD conversion result
// with noise canceling
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
#asm
    in   r30,mcucr
    cbr  r30,__sm_mask
    sbr  r30,__se_bit | __sm_adc_noise_red
    out  mcucr,r30
    sleep
    cbr  r30,__se_bit
    out  mcucr,r30
#endasm
return adc_data;
}
/*
//加热控制及加热指示灯控制程序
void ctrl_led_heat(void)
{
if (temprature_real >= temprature_set)
   {HEAT_CTRL = 1;      HEAT_LED = 0;}           //实际温度大于等于设定温度停止加热且加热指示灯灭
else if (temprature_real < temprature_set)
   {HEAT_CTRL = 0;      HEAT_LED = 1;}           //实际温度小于设定温度开始加热且加热指示灯亮
}
*/
//带占空比控制的加热控制及加热指示灯控制程序
void ctrl_led_heat1(void)
{float point_onoff;
if (temprature_real < temprature_set-temp_step)       //temp_step为门限
   {HEAT_CTRL = 0;HEAT_LED = 1;counter_zhankongbi=0;}   //实际温度小于设定温度点动门限,开始持续加热且加热指示灯亮
else //if ((temprature_real >= temprature_set-temp_step) && (temprature_real < temprature_set))
   {if (counter_zhankongbi < max_cnt_zkb)     
    counter_zhankongbi +=1;            //占空比计数器加1,temp_mullnum * temp_step <= max_cnt_zkb
    point_onoff = temp_kp*(temprature_set-temprature_real)+feedback+feedback1;      //计算PID控制输出值
    if (point_onoff>max_cnt_zkb) {point_onoff = max_cnt_zkb;}
    if (point_onoff<0) {point_onoff = 0;}          //point_onoff在0到max_cnt_zkb之间//
    if (counter_zhankongbi < point_onoff) 
    {HEAT_CTRL = 0;HEAT_LED = 1;}      //加热
    else  //停止加热                   //占空比计数器加到max_cnt_zkb时置零
    {HEAT_CTRL = 1;HEAT_LED = 0;if (counter_zhankongbi == max_cnt_zkb) counter_zhankongbi=0;}
   }    //在点动门限与设定温度之间时,采取点动加热占空比越靠近设定温度时加热时间占空比越小
//else if(temprature_real >= temprature_set)
//   {HEAT_CTRL = 1;HEAT_LED = 0;counter_zhankongbi=0;}   //实际温度大于等于设定温度停止加热且加热指示灯灭
}   

//////////////////////////////////////////////////////////////////////  
//微分项
void ctrl_heat_feedback(void)          //温度在加热功率控制范围内才反馈,瞬时温度不会变化反馈函数必须间隔适当时间调用
{//float feedback_f;                    //单次循环产生的反馈量
 if (t_n_1==0)
 t_n_1=temprature_real;   //tr_n_1为初始化首次值
 if (temprature_real >= temprature_set-temp_step) 
 feedback1 = temp_kp*20*(t_n_1 - temprature_real);     //微分时间与采样周期比值为20
 t_n_1=temprature_real;             //保存上次的温度值 
 if (feedback1>100){feedback1=100;}
 else if (feedback1<-100){feedback1=-100;}
} 
//积分项
void ctrl_heat_feedback1(void)
{if (temprature_real >= temprature_set-temp_step)
 {feedback += temp_kp*(temprature_set - temprature_real)/1600;}          //积分时间与采样周期比值为1600
 else
 {feedback = 0;}
 if (feedback>100){feedback=100;}
 else if (feedback<-100){feedback=-100;}
}
////////////////////////////////////////////////////////////////////////
/*interrupt [TIM2_OVF] void tim2_isr(void)
{
if(timer2_counter<4000)
    timer2_counter++;
else
    timer2_counter=0;
}*/
///////////////////////////////////////////////////////////////////////
//加热控制及加热指示灯控制程序
/*void ctrl_led_heat_ld(void)
{
if (temprature_real >= temprature_set)
   {HEAT_CTRL = 1;      HEAT_LED = 0;}           //实际温度大于等于设定温度停止加热且加热指示灯灭
else
   { 
   if(temprature_set-temprature_real>5)
        {
        HEAT_CTRL = 0;
        HEAT_LED = 1;
        }           //实际温度小于设定温度开始加热且加热指示灯亮
   else if(temprature_set-temprature_real>4)
        {
        if((timer2_counter%2)==0) // 
            {
            HEAT_CTRL=0;
            HEAT_LED=1;
            }
        else
            {
            HEAT_CTRL=1;
            HEAT_LED=0;
            }
        }
   else if(temprature_set-temprature_real>3)
        {
        if((timer2_counter%4)==0)
            {
            HEAT_CTRL=0;
            HEAT_LED=1;
            }         
        else
            {
            HEAT_CTRL=1;
            HEAT_LED=0;
            }
        } 
   else if(temprature_set-temprature_real>2)
         {
        if((timer2_counter%8)==0)
            {
            HEAT_CTRL=0;
            HEAT_LED=1;
            }         
        else
            {
            HEAT_CTRL=1;
            HEAT_LED=0;
            }
        } 
   else if(temprature_set-temprature_real>1)         //此处是否为>1//////////////////////////////////
         {
        if((timer2_counter%16)==0)
            {
            HEAT_CTRL=0;
            HEAT_LED=1;
            }         
        else
            {
            HEAT_CTRL=1;
            HEAT_LED=0;
            }
        }
   else
       {
        if((timer2_counter%32)==0)
            {
            HEAT_CTRL=0;
            HEAT_LED=1;
            }         
        else
            {
            HEAT_CTRL=1;
            HEAT_LED=0;
            }
        }
   }
}*/ 
//////////////////////////////////////////////////////////////////

//温度计算程序,计算后temprature_real的取值为20~120,10,130
/*void caculate (void)
{
 signed int TEMP_REAL;
 float ADC_DATA;             //ADC_DATA必须定义为浮点型,否则ADC_DATA)/0x3ff表达式的得不到精确的计算结果
 ADC_DATA=read_adc(0);                                                  //读通道0转换后的值 
 TEMP_REAL = ((135.0-0.0)/(2.56-0.6))*(2.56*((ADC_DATA)/0x3ff)-0.6);    //计算实际温度值ADC_DATA)/0x3FF始终为0或1
 if  (TEMP_REAL < dis_min)
     temprature_real=dis_min - 2;                                     //小于dis_min时复值为小于dis_min的一个正数
 else if  (TEMP_REAL > dis_max)
     temprature_real=dis_max + 2;                                     //大于dis_max时复值为大于dis_max的一个大于255的值方便计算数码管的段码
 else
     temprature_real=TEMP_REAL;                                         //温度在20--120之间的整数
 
 }
 */
///////////////////////////ly/////////////////////////////////////////// 
 //温度计算公式

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?