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

📄 mega48-1.c

📁 采用ATMEGA48设计制作低成本高精度的数字温度计
💻 C
字号:
#include <iom48v.h> 
#include <macros.h> 
#define uchar unsigned char
#define uint unsigned int
#define LED_NUM    PORTD
#define LED_VALUE  PORTB
#define key_set (PIND&0x02)  
#define key_up (PIND&0x04)
#define key_down (PIND&0x08)
//Pc2、Pc3、Pc4为set,up,down键
/***********************温度表 -50 度到 110 度*****************************/
const uint  v_table[161]={
154,163,173,182,193,203,214,226,238,251,            //-50---- -41
264,278,292,308,323,340,357,374,392,411,            //-40---- -31
431,452,473,495,518,542,566,591,617,643,            //-30---- -21
671,699,729,759,790,821,854,887,921,956,            //-20---- -11
991,1028,1066,1104,1143,1182,1223,1264,1305,1347,   //-10---- -1
1390,1433,1478,1522,1567,1613,1659,1705,1751,1798,  //0---- 9
1845,1893,1940,1989,2036,2084,2132,2180,2228,2277,  //10---- 19
2324,2372,2419,2467,2514,2561,2608,2654,2700,2746,  //20---- 29
2791,2836,2880,2924,2967,3010,3053,3094,3135,3176,  //30---- 39
3216,3255,3294,3332,3370,3407,3443,3478,3513,3548,  //40---- 49
3581,3614,3647,3679,3710,3740,3770,3799,3828,3856,  //50---- 59
3883,3910,3936,3962,3987,4011,4035,4058,4081,4103,  //60---- 69
4125,4146,4167,4187,4207,4226,4244,4263,4280,4298,  //70---- 79
4315,4331,4347,4363,4378,4393,4407,4422,4436,4449,  //80---- 89
4462,4475,4487,4499,4511,4523,4534,4545,4556,4566,  //90---- 99
4576,4586,4595,4605,4614,4623,4631,4640,4648,4656,  //100--- 109
4664,} ;                                             //110
/*****************************************************************************/
//共阴数码管"0~9",
uchar dis_1[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,};
//"熄灭","-"(负号),"-","_","Y","H","C"字段码
uchar dis_2[7]={0x00,0x40,0x01,0x08,0x6e,0x76,0x39};
uchar Data[3]={0,0,0}; //显示缓冲数据
uint  v=0,dis_v,bh_v,dis_v_1;//实时温度值, 显示用的温度值
uchar hot_warning[2]={0x00,0x00};//制热模式限定值、制冷模式限定值
uchar cool_delay = 0;    //压缩机停机再开机延时时间
uchar setting_mode = 0;  //温度控制器模式,0x6e:制热模式;0x76:制冷模式,
uchar Write_EEPROMData[5]={0,0,0,0,0};//设定数值写到EEPROM数据缓冲
uchar Read_EEPROMData[5]={0,0,0,0,0};//从EEPROM读设定数值到缓冲
//数据为:制热模式限定值、制冷模式限定值、压缩机延时开机时间、工作模式、温度校正

uchar flag=1,nc_flag=0,no_flag=0;  //负号标志位,传感器断线标志位,传感器短路标志位
uchar CNT=0;    //延时AD
uchar CNT_PV;     //连续采样8次后取平均
/*****************************************************************************/
//函数名	:DelayMs
//属性		:私有
//功能		:延时
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:2007.1.2
//修改人	:mengxy
/*****************************************************************************/
void DelayMs(uint i)            
{uint j;
  for(;i!=0;i--)
   {for (j=500;j!=0;j--)          //延时1ms
   {
    //WDR();//复位看门狗
   }
   }
}
/*****************************************************************************/
//函数名	:WDT_off
//属性		:私有
//功能		:关闭看门狗
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:2007.1.2
//修改人	:mengxy
/*****************************************************************************/
void WDT_off(void)
{
   /* 置位 WDTOE 和WDE */ 
   WDTCSR = (1<<WDCE) | (1<<WDE); 
   /* 关闭WDT */ 
   WDTCSR = 0x00; 
}
/*****************************************************************************/
//函数名	:port_init
//属性		:私有
//功能		:机器初始化
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:
//修改人	:
/*****************************************************************************/
void port_init(void)
{    CLI();          //关中断
    MCUSR=0xf7;  //关看门狗 
    WDT_off();    
	CLKPR = 0x80;
    CLKPR = 0x00;   //时钟分频因子为1	
	DDRB = 0xff;    //数码管段驱动
	PORTB = 0xff;
//将PC0、PC1、PC2、PC3定义为输入,不带上拉电阻
    DDRC=0x00; //
    PORTC=0x00; // 将 PORT 置0,没有上拉电阻
	DDRD = 0x0f;    //PD0.1.2 位驱动,PD5.6.7键盘输入
	PORTD = 0x0f;
	
}
/*****************************************************************************/
//函数名	:ceshi_led
//属性		:私有
//功能		:机器初始化,测试数码管,全亮
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:
//修改人	:
/*****************************************************************************/
void ceshi_led(void)
{
   PORTD=0x07;  //打开低三位   开机初始化画面显示
   PORTB=0x00;   //测试数码管
   DelayMs(500);
   PORTB=0xff;  
   DelayMs(500);
}
/*****************************************************************************/
//函数名	:AdcConvert
//属性		:私有
//功能		:开始AD转换
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:2007.1.2
//修改人	:mengxy
/*****************************************************************************/

void get_adc_value(uchar adc_pin)          //开始AD转换,单次转换
{  
    CLI();
	ADMUX = (1<<REFS0)|(0<<REFS1)|adc_pin; //参考电压源选择AVCC
	ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);
	SEI();		    //开中断
	{
	ADCSRA |= (1<<ADSC);         //开始AD
	DelayMs(1); 
	//ADCSRA &= ~(1<<ADSC); 
	
    }
 
}
/*****************************************************************************/
//函数名	:adc_isr
//属性		:中断
//功能		:获取AD转换结果
//输入参数	:无
//输出参数	:无
//返回值	:
//修改日期	:2007.1.2
//修改人	:mengxy
/*****************************************************************************/

#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)          //AD转换 计算结果,以查表方便,获取的数值直接查表
{    uint temp,temp1,temp2,temp3;
 	 temp1 = (uint)ADCL;
	 temp2 = (uint)ADCH;
	 temp3=(temp2<<8)+temp1;
	 v = (49*temp3)/10;
	
      ADCSRA = (1<<ADEN);
	  CLI();
}
/*****************************************************************************/
//函数名	:get_degree
//属性		:私有
//功能		:查表
//输入参数	:v
//输出参数	:v
//返回值	:v
//修改日期	:2007.1.2
//修改人	:mengxy
/*****************************************************************************/
uint get_degree(void)
{
	uchar x,y;
	uint v_big,v_small,v_step;	
	if (v<100)   /////传感器断线AD为0v
	{
	 nc_flag=1;   
	}
	if (v>4800)  /////传感器短路,AD为5v
	{
	 no_flag=1;   
	}
    if(v>100&v<4800)    ///传感器正常,断线\短路标志为0
	{
	 nc_flag=0;
	 no_flag=0;
	}
	for (x=0;x<161;x++) //查表  161个数据
	{
		if (v_table[x] >= v) // 找出电压区域
		{           
		    v_big = v_table[x]; // 区域高段
			v_small = v_table[x-1]; //区域低段
			v_step = (v_big - v_small)/10; //把区域细分成10份
			for (y=0;y<10;y++) // 细分比较
			{
				v_small += v_step;
				if(v < v_small)
				{bh_v=y;}             //温度变化值bh_v。
			}
				
				
					v=x;
					if (x<=49) // 少于51为负温度
					{
						v = 50-v; //加入负号标记
						flag=0;
					}
					else
					{
						v =v-51; //0度修正
						flag=1;
					}
   				    return v;  
			
		};
		
	}  
  return v; 	
}

/*****************************************************************************/
//函数名	:JS_AD_display
//属性		:私有
//功能		:AD数值的显示
//输入参数	:dis_v
//输出参数	:Data[]  显示缓冲区的数值
//返回值	:
//修改日期	:2007.1.3
//修改人	:mengxy
/*****************************************************************************/
void JS_AD_display(void)
{ 
 uchar tempData[3];
 tempData[2]=dis_v/100;   //百位
 tempData[1]=dis_v%100/10;//十位
 tempData[0]=dis_v%10;    //个位
 Data[2]=dis_1[tempData[2]];
 Data[1]=dis_1[tempData[1]];
 Data[0]=dis_1[tempData[0]];
 if(tempData[2]==0)
  {Data[2]=0x00;          //百位为0,不显示
    if(tempData[1]==0)
    {Data[1]=0x00;}          //十位也为零,不显示
   }
 if(flag==0)
 {
  Data[2]=0x40;    //负号标志为0,显示负号
 }
 if(nc_flag==1)
 {Data[2]=0x40;Data[1]=0x40;Data[0]=0x40;}//断线显示:---
 if(no_flag==1)
 {Data[2]=0x39;Data[1]=0x39;Data[0]=0x39;}//短路显示:CCC
}

/*****************************************************************************/
//函数名	:AD_display
//属性		:私有
//功能		:AD数值的显示,显示的时候,刷新AD 数值
//输入参数	:Data[]
//输出参数	:
//返回值	:
//修改日期	:2007.1.3
//修改人	:mengxy
/*****************************************************************************/
void AD_display(void)
{
 uchar i,sel=0x01,ii=0;
 uchar CNT1;
 for(i=0;i<3;i++)
   {
    LED_NUM=sel;   //打开相应的位
   if((dis_v>=20)||(flag==0))    //超温报警,低温报警
	{
	 LED_NUM|=0x08;   //打开PD3
	}
    LED_VALUE=~Data[i];   //共阳数码管,共阴的则~sel,Data[i]
    DelayMs(1);
    sel=sel<<1;
   }
//////显示的时候,刷新AD 数值

  CNT++; 


}
/*****************************************************************************/
//函数名	:pj_v
//属性		:私有
//功能		:进行AD计算
//输入参数	:CNT,get_adc_value(0);get_degree(); 
//输出参数	:
//返回值	:
//修改日期	:2007.1.3
//修改人	:mengxy
/*****************************************************************************/
void pj_v(void)
{
  if (CNT==100)
  {
   CNT=0;
   //////////////////////////////////////
    // CLI();          //关中断
	//ADMUX = (1<<REFS0);	//AVCC, AREF 引脚外加滤波电容,
	//ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);
	//ADEN置位即启动ADC,ADIF: ADC 中断标志,64分频
   //SEI();		    //开中断
////////////////////////////////////
   get_adc_value(0); //进行ADC取样,通道0
   DelayMs(1);   //延时,AD中断
   get_degree(); //查表    
 // if((bh_v>1)& (bh_en=1))  // 温度变化超过0.5度并且bh_en置位,就传递
   dis_v_1=dis_v;     // 传递给显示,精度整定时,bh_en=0,出厂时设置bh_en=1
   dis_v=(v+dis_v_1)/2;//本次数值和上次数值平均
  }
}
/*****************************************************************************/
//函数名	:main
//属性		:私有
//功能		:主函数
//输入参数	:port_init();Get_AD();JS_AD_display();AD_display();
//输出参数	:
//返回值	:
//修改日期	:2007.1.3
//修改人	:mengxy
/*****************************************************************************/
void main(void)
{
 port_init();     //初始化
 ceshi_led();     //测试数码管
 while(1)  
   {   
  AD_display();    //显示
  pj_v();
  JS_AD_display(); //对AD计算,获取显示数据
  }
}
/*****************************************************************************/




⌨️ 快捷键说明

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