⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 用ATmega88的一款温湿度仪的原程序
💻 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 + -