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