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 + -
显示快捷键?