📄 main.c
字号:
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "ht1621.h"
#include "key.h"
#include "display.h"
#include "math.h"
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include "adc.h"
#include "flash_table.h"
#define AD_SE_ADC0 0x00 //ADC0
#define AD_SE_ADC1 0x01 //ADC1
#define AD_SE_ADC2 0x02 //ADC2
#define AD_SE_ADC3 0x03 //ADC3
#define AD_SE_ADC4 0x04 //ADC4
#define AD_SE_ADC5 0x05 //ADC5
long adc_result;
unsigned char adc_ch;
//unsigned int ref=0;
int tempr_max ;
int tempr_min ;
unsigned char hum_max ;
unsigned char hum_min ;
int tempr_adj;
signed char hum_adj;
int tempr;
unsigned char hum;
unsigned char p_key;
unsigned char sign=0x05; //依次是T7、T6、T5、T4、T3、T2、T1、T0的标志位,T0=—&&RH%、T1=F
int CalcTemp(long ResValue);
int CalcHumity(int tTemp,long tRes); //T2=C、T3=MAX、T4=MIN、T5=振铃、T6=声音标志、T7=PM
void initial()
{
DDRD|=0x03; //set PD0 and PD1 to be output pin for LCD
DDRB|=0x02; // set PB1 to be output pin for LCD
DDRB&=0x3E; // set PB0,PB6 and PB7 to be a input pin for key input
DDRD&=0x7F; //set PD7 to be a input pin for key input
TCNT2=206; //set timer2 to interrupt for key scan 50ms中断一次
TCCR2B=0x04; //256分频 频率1k
TIMSK2=0x01;
SMCR=0x02; //ADC 噪声抑制模式
}
void pwm_enable(void)
{
DDRD|=0x60; //pwm需要把端口设置为输出
// DDRD|=0x20;
// TCCR0B&=0x3F; //FOC0B 清零 写寄存器值
/* */
TCCR0A=0xE3; //选择快速pwm 模式,
TCCR0B|=0x01;//0分频,频率是 256K
TCNT0=0;
OCR0B=128;
OCR0A=128 ; //匹配值,输出1K的方波
// TCCR0B|=0xC0; //开始输出pwm波
}
void enable_dormancy(void)
{
ADCSRA&=0x7F;//禁止ADC
SMCR|=0x01;
asm("SLEEP");
}
int main(void)
{
unsigned char key_temp=0;
unsigned int count=0;
long comdata;
long ad_value;
long ad_value2;
long rh;
/* */
CLKPR=0x80; //这是改写CPU时钟的程序,CPU时钟出厂设置为1M,现在设置为256K
CLKPR=0x02;
initial();
pwm_enable();
adc_init(AD_SE_ADC2);
init_ht1621();
eeprom_busy_wait();
tempr_max=eeprom_read_word((unsigned int*)0);
tempr_min=eeprom_read_word((unsigned int*)2);
hum_max=eeprom_read_byte((unsigned char*)4);
hum_min=eeprom_read_byte((unsigned char*)5);
tempr_adj=eeprom_read_word((unsigned int*)6);
hum_adj=eeprom_read_byte((unsigned char*)8);
asm("sei");
tempr=783;
hum=65;
display_T(tempr,1);
display_H(hum,1);
while(1)
{
Scankey(); //50ms扫描一次按键
key_temp=Getkey(); //读取按键值
if(key_temp)
key_deal(key_temp); //处理按键
count++;
count=count%200;
if((count%100)==0)
{
adc_init(AD_SE_ADC5);
comdata=adc_read(AD_SE_ADC5);
adc_result=1024-comdata;
comdata=comdata*100000; //将计算好的电阻值放大1000倍
comdata=comdata/adc_result;
tempr=CalcTemp(comdata);
if(tempr+tempr_adj>tempr_max)//更新最大最小值
{
tempr_max=tempr+tempr_adj;
eeprom_write_word((unsigned int*)0,tempr_max);
}
else if(tempr+tempr_adj<tempr_min)
{
tempr_min=tempr+tempr_adj;
eeprom_write_word((unsigned int*)2,tempr_min);
}
display_T(tempr,1); //显示温度值
}
if((count%98)==0)
{
adc_init(AD_SE_ADC2);
while(PIND&0x40); //等待PWMA输出低电平
ad_value=adc_read(AD_SE_ADC2);//采样湿度传感器电压值
ad_value*=100; //采样值放大100倍
if(ad_value<8000)
{
adc_init(AD_SE_ADC0);
while(PIND&0x40);
ad_value=adc_read(AD_SE_ADC0);//采样放大了11倍后的值
ad_value*=9;
}
adc_init(AD_SE_ADC1);
while(PIND&0x40);
ad_value2=adc_read(AD_SE_ADC1);//采样100K电压值
ad_value2*=100;
ad_value2-=ad_value;
rh=10000*ad_value/ad_value2; //rh 为湿敏电阻值放大了100倍,单位是k欧
hum=CalcHumity(tempr,rh);
if(hum+hum_adj>hum_max)
{
hum_max=hum+hum_adj;
eeprom_write_byte((unsigned char*)4,hum_max);
}
else if(hum+hum_adj<hum_min)
{
hum_min=hum+hum_adj;
eeprom_write_byte((unsigned char*)5,hum_min);
}
display_H(hum,1);
}
enable_dormancy(); //使能休眠50ms
}
return 1;
}
ISR (TIMER2_OVF_vect) //进入此中断则把cpu从休眠中唤醒
{
ADCSRA |= 0x80;//使能ADC
TCNT2=206;
}
int CalcTemp(long ResValue)
{
unsigned char i;
volatile long tTemp;
volatile long t0,t1,tt;
for(i=0;i<29;i++)
{
t1 = pgm_read_dword(R + i);
if(ResValue > t1)
{
break;
}
}
t0 = pgm_read_dword(R + i-1);
tt = pgm_read_dword(T + i);
tTemp= tt;
tTemp=tTemp -(ResValue-t1)*50 /(t0-t1);
return(tTemp);
}
//tRes 湿敏电阻值,真实值乘以100再代入
int CalcHumity(int tTemp,long tRes)
{
volatile unsigned char i,j;
int tLogRes;
volatile int r0,r1,r2,r3,h0,r4;
tLogRes = (log10((double)tRes)-2)*1000;
//寻找温度范围,比如13度在10-15度之间,此时i应等于3 .表示3*5=15;
for(i=1;i<10;i++)
{
if(tTemp <= (50*i)) //将5*i修改为50*i,这样输入温度值,可以是放大了10倍以后的值
break;
}
if(i >=10) //温度大于表中最大温度45度
{
tTemp = 45;
i = 9;
}
//寻找湿度所在区间,比如20%-30%区间。j = 0 表示湿度小于20% j=1表示湿度小于30%
for(j=0;j<8;j++)
{
r4= pgm_read_word(&H[i-1][j]); //先读取温度值“大”的电阻值比较
if(tLogRes >= r4)
break;
}
//边界条件
if(j == 0) //表示电阻大于大于表中最左侧电阻阻值
{
tLogRes = pgm_read_word(&H[i-1][j]); //有没有必要?
j = 1;
}
if(j>=8) //电阻小于表中最右侧电阻阻值
{
j = 7;
tLogRes = pgm_read_word(&H[i-1][j]);
}
if(i == 1) //温度小于表中最小温度5度
{
tTemp = 5; //这个温度值不要变是不是更好一些?!
i = 2;
}
r0 = pgm_read_word(&H[i-1][j]); //r0为湿度为j*10+20,温度为i*5下的电阻
r1 = pgm_read_word(&H[i-2][j]); //r1 为湿度为j*10+20,温度为(i-1)*5下的电阻
r2 = (r0-r1)*(tTemp-i*5)/5+r0; //r2为湿度为j*10+20,温度为tTemp下的电阻(log型式)
r3 = pgm_read_word(&H[i-1][j-1]); //r3为湿度为(j-1)*10+20,温度为i*5下的电阻
h0 = (tLogRes - r2)*10/(r0-r3)+j*10+20;
return h0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -