temprature.c

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

C
640
字号
 void caculate1(void)
{
float ntc_v,ntc_r;           //保存NTC的电压值和NTC当前的阻值
float TEMP_REAL;

 ntc_v=5.1*ADC_DAT/1023;   //计算NTC上的电压
 ntc_r=R_fenya*ntc_v/(VCC-ntc_v); //计算当前NTC的阻值
 TEMP_REAL=298.15*B_NTC/(B_NTC+298.15*log(ntc_r/R25_NTC))-273.15;//计算当前温度  
 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之间的整数
}
/////////////////////////////////////////////////////////////////////////////   
//浮点数四舍五入函数  
unsigned int float_ceil(float x_1)
{unsigned int y_1;
y_1 = x_1;
if ((x_1-0.5)>=y_1)
y_1 = y_1 +1;
return y_1;
} 
//温度显示服务程序
void display_service(void)
{  
float  temprature_display;
unsigned int TEMP_DISPLAY;
//if (counter_soft == 0)
//   flag_dis = 0;                                  //软件记数器为0时置显示标志为0
if (flag_dis == 0) //&& flag_tem == 0)                   //显示标志为0时实际温度送显示数据存储器
   temprature_display = temprature_real; 
else 
   temprature_display = temprature_set;           //显示标志为1时设定温度送显示数据存储器
                                                  //LED显示段码转换程序
if (temprature_display < dis_min)                      //小于10时显示L
   {
    buffer_dis[0] = led_segtab[18];
    buffer_dis[1] = led_segtab[18];
    buffer_dis[2] = led_segtab[17];
   }
else if (temprature_display > dis_max)                //大于120时显示H
   { 
    buffer_dis[0] = led_segtab[18];
    buffer_dis[1] = led_segtab[18];
    buffer_dis[2] = led_segtab[16];
   }
else if (temprature_display >= 100)            //在100~120之间时显示实际温度值
   {TEMP_DISPLAY = float_ceil(temprature_display);         //浮点数不能取模
    buffer_dis[2]=TEMP_DISPLAY / 100;       //百位数
    buffer_dis[2]=led_segtab[buffer_dis[2]];
    
    buffer_dis[1]=TEMP_DISPLAY % 100;       //十位数
    buffer_dis[1]=buffer_dis[1] / 10;
    buffer_dis[1]=led_segtab[buffer_dis[1]];
    
    buffer_dis[0]=TEMP_DISPLAY % 10;        //个位数
    buffer_dis[0]=led_segtab[buffer_dis[0]];    
   }
else                                        //在10到99之间
  /*{if (flag_tem==1 && counter_soft == 0)  //加热达到设定温度误差范围内,不显示小数点
   {TEMP_DISPLAY = float_ceil(temprature_display);         //浮点数不能取模
    buffer_dis[2]=TEMP_DISPLAY / 100;       //百位数
    if (buffer_dis[2]==0){buffer_dis[2]=18;} 
    buffer_dis[2]=led_segtab[buffer_dis[2]]; 
        
    buffer_dis[1]=TEMP_DISPLAY % 100;       //十位数
    buffer_dis[1]=buffer_dis[1] / 10;
    buffer_dis[1]=led_segtab[buffer_dis[1]];
    
    buffer_dis[0]=TEMP_DISPLAY % 10;        //个位数
    buffer_dis[0]=led_segtab[buffer_dis[0]];   
   }
    else */                                  //显示小数点
   {TEMP_DISPLAY = float_ceil(temprature_display*10);   //将十分位转到个位
    buffer_dis[2]=TEMP_DISPLAY / 100;       //十位数
    if (buffer_dis[2]==10){buffer_dis[2]=1;}
    buffer_dis[2]=led_segtab[buffer_dis[2]];
    
    buffer_dis[1]=TEMP_DISPLAY % 100;       //个位数
    buffer_dis[1]=buffer_dis[1] / 10;     
    if (TEMP_DISPLAY / 100==10)
    {buffer_dis[1]=led_segtab[buffer_dis[1]];}
    else
    {buffer_dis[1]=(led_segtab[buffer_dis[1]])&0xfd;}     //个位点亮小数点
     
    buffer_dis[0]=TEMP_DISPLAY % 10;        //十分位
    buffer_dis[0]=led_segtab[buffer_dis[0]]; 
   } 
    
                                                   
} 

//温度显示程序
void display (void)
{
LED_DATA = buffer_dis[0];LED_S3=1;                 //显示第1位数据
delay_ms(20);LED_S3=0;                              //延时6ms后关闭第1位显示,防止闪烁

LED_DATA = buffer_dis[1];LED_S2=1;                 //显示第2位数据
delay_ms(20);LED_S2=0;                              //延时6ms后关闭第2位显示,防止闪烁

LED_DATA = buffer_dis[2];LED_S1=1;                 //显示第3位数据
delay_ms(20);LED_S1=0;                              //延时4.25ms后关闭第3位显示,防止闪烁
                                                   //最后一位延迟4.25ms是为了补偿主程序耗费的时间,亮度更均匀
}

//初始化程序
void initialize (void)
{
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=In 
// State6=1 State5=0 State4=1 State3=1 State2=1 State1=1 State0=t 
PORTC=0x5E;                    //PORTC.0为NTC输入,必须设为输入高阻态
DDRC=0x7E;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=Out Func0=Out 
// State7=1 State6=1 State5=1 State4=1 State3=P State2=P State1=1 State0=1 
PORTD=0xFF;
DDRD=0xF3;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 run
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
/////////////////////////////////////////////////////////////
TCCR2=0x00;             //工作在普通模式 应该为0x06 选择256预分频才能保证T2的益出周期大于主循环运行周期
/////////////////////////////////////////////////////////////
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: On
// INT1 Mode: Falling Edge
GICR|=0xC0;
MCUCR=0x0A;
GIFR=0xC0;                       //写1清零外部中断标志

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

////////////////////////////////////////////////////  
//timer2_counter=0;//定时器2溢出中断计数初始化
//TIMSK|=0x40;//定时器2溢出使能
///////////////////////////////////////////////////

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 125.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x8d;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/1024k
#pragma optsize-
WDTCR=0x1E;
WDTCR=0x0E;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

//控制变量初试化
delay_ms(100);                                                  //延时等待eeprom准备好
temprature_set = EEPROM_read(0);                                //装载EEPROM的0单元中保存的用户设定温度
if (temprature_set > set_max || temprature_set < set_min)       //如果设定温度值大于设定温度上限
{temprature_set = 50;                                           //将设定温度值初始化为50度
 EEPROM_write(0,temprature_set);                                //保存设定温度值到EEPROM的0单元
}
flag_dis = 1;                                                   //显示标志置1,开机显示设定温度
counter_soft = temp_set_dis_time;                               //设置温度显示计数置100  

// Global enable interrupts
#asm("sei")

}
void adc_10th (void)
{float sum_temp10;
 unsigned char numok_temp10;
for (n_adc=0,sum_temp10=0;n_adc < 10;n_adc++)
 {Adc_Data_ad1[n_adc] = read_adc(0);                    //连续采样10次
  sum_temp10 += Adc_Data_ad1[n_adc];         
  //standard_data += Adc_Data_ad[n_adc];
 }
 //standard_data = standard_data / 10;        
        ADC_DAT = sum_temp10 / 10;
        for (n_adc=0,numok_temp10=0;n_adc < 10;n_adc++)
        {if (abs(Adc_Data_ad1[n_adc]-ADC_DAT)<=2)
            numok_temp10++;
         else 
            sum_temp10 -= Adc_Data_ad1[n_adc];   
        }
        if (numok_temp10 >0)
          ADC_DAT = sum_temp10 / numok_temp10; 
        caculate1();
        //if (fabs(temprature_set-temprature_real)<0.1)        //不显示小数点标志
        //{flag_tem = 1;}
        //if (tem_setn == 0){tem_setn = temprature_set;}
        //if (temprature_set != tem_setn){flag_tem = 0;tem_setn = temprature_set;}
        //if (fabs(temprature_set-temprature_real)>10)
        //{flag_tem = 0;}
        //adc采样去掉干扰信号后的平均值,10次的值相等才更新  
      /*  if (fabs(temprature_set-temprature_real)<0.1)
        {
        if(feedback<5)
        feedback = 5; 
        }*/
        
 //standard_data = 0;
}
void main(void)
{unsigned char counter_adc;                   //控制调用ADC采样计算实际温度延迟时间 
 unsigned char KI_T;//,KD_T;
// Declare your local variables here 
initialize ();                                //调用初始化程序
while (1)
      {
      // Place your code here 
      #asm("wdr")                             //复位看门狗
      if (counter_soft == 0)                  //显示实际温度时才读EEPROM,才能保证改变的设定值写入EEPROM
      {temprature_set = EEPROM_read(0);        //装载EEPROM中保存的用户设定温度,初始状态为50度 
      flag_dis = 0; }                          //软件记数器为0时置显示标志为0
      if (flag_dis == 1)                      //flag_dis == 1的情况下才有可能有按键按下
      {counter_soft -=1;                      //显示设定温度时软件计数器counter_soft减1
       if ((counter_soft == 98)||(counter_soft == 78))
          {  if (KG1_UP_PD2 == 0)               //判断KG1是否按下        
               {
                  if (temprature_set < set_max)      //设定温度值不能高于110度
                   {temprature_set += 1;              //按下KG1时设定温度加1  
                    flag_int = 1;                                    //置产生了中断的标志
                    //flag_tem = 0;             //设定温度改变时置0
                    //EEPROM_write(0,temprature_set);    //保存设定温度值到EEPROM的0单元 
                   }
                   counter_soft = temp_set_dis_time-2;  //复位显示延迟计数器,-2防止counter_soft再次出现98  
                   flag_dis = 1;                 
               }
             else if (KG2_DOWN_PD3 == 0)       //判断KG2是否按下  
               {
                  if (temprature_set > set_min)       //设定温度值不能低于30度                         
                  {temprature_set -= 1;                //按下KG2时设定温度减1
                   flag_int = 1;                                    //置产生了中断的标志
                   //flag_tem = 0;              //设定温度改变时置0     
                  //EEPROM_write(0,temprature_set);     //保存设定温度值到EEPROM的0单元
                  }
                  counter_soft = temp_set_dis_time-2;  //复位显示延迟计数器,-2防止counter_soft再次出现98   
                  flag_dis = 1;               
               }
           }
       }
      if (counter_soft == 20 && flag_int == 1)          //保证只有设定温度值改变了,且按键已经弹起时才写EEPROM
      {EEPROM_write(0,temprature_set);flag_int = 0;}   //当counter_soft=1时,按键已经弹起,保存设定温度值到EEPROM的0单元 
      adc_10th ();                                     //调用采样程序
      #asm("wdr")                             //复位看门狗
      if (flag_dis == 1)
      {display_service();}                            //调用显示服务程序 
      else if (counter_adc<adc_time)
      {counter_adc++;}                                  //采样间隔为adc_time*20ms左右
      else
      {display_service();counter_adc=0;}              //调用显示服务程序,采样和控制实时,显示刷新频率可低点
      if (KI_T<10)
      {KI_T++;}
      else
      {ctrl_heat_feedback1();ctrl_heat_feedback();KI_T = 0;}     //积分项计算
      //if (KD_T<6)
      //{KD_T++;}
      //else
      //{ctrl_heat_feedback();KD_T = 0;}     //微分项计算
      ctrl_led_heat1();                               //调用加热指示和加热控制程序  
      #asm("wdr")                                     //复位看门狗  
      display();                                      //调用显示程序 
      };
}

⌨️ 快捷键说明

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