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

📄 温度测量.c

📁 一个基于MSP430F135单片机的热量计量表的C语言原码
💻 C
字号:
#include  <msp430x41x.h>

#include  "main.h" //自己定义的必要的结构和变量

void delay(INT16U dd);

//以下为初始化函数
void initial_port(void);//初始化端口
void AD_sampling(INT16U * AD_temp);
float calc_Temperature(float R);
INT8U long2dec(INT32U d, INT32U * p);

//以下为显示函数
void display_LCD_all_on(void);//点亮所有LCD段
void display_LCD_all_off(void);//熄灭所有LCD段
void display_INT32U(INT32U temp);
void display_flag_clear(void);//为了节约空间而用
void display_float(float QQ, INT8U pos);

//以下为主程序逻辑函数
void monitor_key(void);//对按键进行监控
void monitor_time(void);//对时间进行监控
void monitor_AD(void);//对AD采样进行监控
void monitor_display(void);

static struct BIT16_flag common_flag1={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#define		is_one_second			common_flag1.b0
#define		is_display_now			common_flag1.b1
#define		is_k1_key_ok 			common_flag1.b2
#define		is_AD_sample_time		common_flag1.b5
#define		is_start_measure_R	    common_flag1.b6	//AD测量

static struct BIT16_flag display_flag1={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#define     is_display_temperature_in			display_flag1.b2
#define		is_display_temperature_out  		display_flag1.b3
#define		is_display_INT32U				 	display_flag1.b10

INT8U 	start_measure_status=0;

INT8U  	one_second=0, k1_key_page=0;
INT16U	AD_sample_time=0;

INT8U  	LCD_buf[9], test=0;//LCD 缓存

INT16U	N_Pt_IN[2], N_Pt_OUT[2], N_ref, temp_t=0;//存放采样值


//以下要保存
float 	T1, T2, T1_adjust_coefficient=0, T2_adjust_coefficient=0;	//进水温度,出水温度


//主函数
void main(void)
{	
	initial_port();
		
	_EINT();
	display_LCD_all_off();
			
	while(1){
		monitor_time();
		monitor_key();
		
		monitor_AD();
		monitor_display();
		LPM3;		
  	}
}

void display_flag_clear(void)
{
	INT16U * ptr_INT16U;
	
	ptr_INT16U = (INT16U*) &display_flag1;
	*ptr_INT16U = 0;
	display_LCD_all_off();
	
	is_display_now=1;
}

//功能:按键
//描述:无
//参数:无
//返回:无
void monitor_key(void)
{	
	if(is_k1_key_ok)
	{
		is_k1_key_ok=0;
		
		///////////////////////////////////////////////////////////////
		switch(k1_key_page)
		{				
		    case 0:
		    	//显示进水温度 (°C)
		    	display_flag_clear();		      		
		    	is_display_temperature_in=1;		    	
		    	break;
		    case 1:
		    	//显示出水温度(°C)
		    	display_flag_clear();	      		
		    	is_display_temperature_out=1;
		      	break;
		    default:
		      	break;		
		}
		k1_key_page++; k1_key_page%=2;
	}
}

void monitor_display(void)
{
	
	if(is_display_temperature_in)
	{
		display_float(T1,2);
	}
	if(is_display_temperature_out)
	{
		display_float(T2,2);
	}	
	if(is_display_INT32U)
	{
		display_INT32U((INT32U)temp_t);
	}
}

//功能:时间处理程序
//描述:无
//参数:无
//返回:无
void monitor_time(void){
	
	if(is_one_second)//一秒钟到了
	{
		is_one_second=0;
		
		AD_sample_time++;
		if(AD_sample_time>=5) //10秒
		{
			AD_sample_time=0;
			is_AD_sample_time=1;
		}	
	}	
}

//功能:AD处理
//描述:无
//参数:无
//返回:无
void monitor_AD(void)
{		
	if(is_AD_sample_time)//测量时间到了
	{
		is_AD_sample_time = 0;
		is_start_measure_R = 1;	//启动测量程序
	}
	if(is_start_measure_R)
	{		
		switch(start_measure_status)
		{
			case 0: 	//测量标准电阻				
				delay(30000);				
				P6OUT |= (BIT0+BIT2+BIT3);//P6.0=1, 打开4051
				//P6.1=0, P6.2=1, P6.3=1选择精密电阻
				P6OUT &= ~BIT1;
				AD_sampling(&N_ref);												
				
				start_measure_status++;
				break;			
			case 1: 	//测量Pt_IN				
				delay(50000);				
				P6OUT |= (BIT0+BIT1+BIT3);//P6.0=1, 打开4051
				//P6.1=1, P6.2=0, P6.3=1选择Pt_IN
				P6OUT &= ~BIT2;
				AD_sampling(&N_Pt_IN[0]);								
				
				start_measure_status++;				
				break;			
			case 2://测量Pt_OUT
			  	delay(30000);	
				P6OUT |= (BIT0+BIT1+BIT2);//P6.4=1, 打开4051
				//P6.1=1, P6.2=1, P6.3=0选择Pt_OUT
				P6OUT &= ~BIT3;
				AD_sampling(&N_Pt_OUT[0]);				
				
				start_measure_status++;
			  	break;
			case 3:				
			  //以下为进水Pt, 取1k,1.4k两个点的值
			  			
			  N_Pt_IN[1] = N_Pt_IN[0]-N_ref;	
			
			  //N_Pt_IN[1] -= 128;
			
			  T1 = 1000+400*((float)N_Pt_IN[1])/2021.1;
			
			  if((T1<=1600)&&(T1>=1000))//不能超过150°
			  {
			  	T1 = calc_Temperature(T1);
			  	if(T1>T1_adjust_coefficient) T1=T1-T1_adjust_coefficient;	//此处进行微调			  	
			  	else T1=0;
			  }		  	
			  else
			  {
			  	T1=0;
			  }
			
			  //以下为出水Pt,取1k,1.4k两个点的值
			  N_Pt_OUT[1] = N_Pt_OUT[0]-N_ref;			  		
			
			  //N_Pt_OUT[1]-= 181;//调试时需要注释掉		  					
			
			  T2 = 1000+400*((float)N_Pt_OUT[1])/2031.1;
			
			  if((T2<=1600)&&(T2>=1000))//不能超过150°
			  {
			  	T2 = calc_Temperature(T2);
			  	if(T2>T2_adjust_coefficient) T2 = T2-T2_adjust_coefficient;//此处进行微调
			  	else T2=0;
			  }
			  else
			  {
			  	T2=0;
			  }
			
			  //++++++++++以下调试用+++++++++++++
			  #if 1 //校准时需要为1,校准完后改为0
			  display_flag_clear();			
			  temp_t = N_Pt_IN[1];//选择其中一个
		      //temp_t = N_Pt_OUT[1];
		      is_display_INT32U=1;
			  #endif
			
			  start_measure_status=0;
			  is_start_measure_R=0;
			  break;
			default:
				break;
		}
	}
}

//显示0~65535的数字
void display_INT32U(INT32U t)
{
	INT32U temp=0;
	INT8U i=0, len;
	
	len = long2dec(t, &temp);
	
	for(i=0;i<len;i++)
	{
		LCD_buf[7-i] = (temp&0x0000000f);
		temp>>=4;
	}
	for(i=0;i<(7-len);i++)
	{
		LCD_buf[i]=16;
	}
}

void display_float(float QQ, INT8U pos)//显示pos=2,3,4位小数点
{
	INT32U temp=0, temp2=0;
	INT8U i=0, len;
	INT8U pp=2;
	
	pp= pos;
	if(pos==2)
	{
		temp2 = (INT32U) (QQ*100);
		if(QQ>=0.01) goto display_1;
		else goto display_2;
	}
	if(pos==3)
	{
		temp2 = (INT32U) (QQ*1000);
		if(QQ>=0.001) goto display_1;
		else goto display_2;
	}
	if(pos==4)
	{
		temp2 = (INT32U) (QQ*10000);
		if(QQ>=0.0001) goto display_1;
		else goto display_2;
	}
	if(pos==5)
	{
		temp2 = (INT32U) (QQ*100000);
		if(QQ>=0.00001) goto display_1;
		else goto display_2;
	}
display_1:
		len = long2dec(temp2, &temp);
		if(len<=pp)//处理小数点
		{
			for(i=0;i<len;i++)
			{
				LCD_buf[7-i] = (temp&0x0000000f);
				temp>>=4;
			}
			for(i=0;i<=pp-len;i++)
			{
				LCD_buf[7-pp+i] = 0;
			}		
			for(i=0;i<=6-pp;i++)
			{
				LCD_buf[i]=16;
			}
		}
		else
		{			
			for(i=0;i<len;i++)
			{
				LCD_buf[7-i] = (temp&0x0000000f);
				temp>>=4;
			}
			for(i=0;i<(7-len);i++)
			{
				LCD_buf[i]=16;
			}
		}
		goto display_3;
display_2:
	//显示0
	for(i=0;i<=6;i++)	
	{
		LCD_buf[i] = 16;
	}
	LCD_buf[7] =0;
display_3:
    _NOP();
}


//功能:点亮所有LCD段
//描述:无
//参数:无
//返回:无
void display_LCD_all_on(void)
{
	INT8U i;
	for(i=0;i<=9;i++){//全部点亮LCD段
		LCD_buf[i] = 18;
		LCDMEM[i] |= 0xff;
	}	
}

//功能:熄灭所有LCD段
//描述:无
//参数:无
//返回:无
void display_LCD_all_off(void)
{
	INT8U i;
	for(i=0;i<=9;i++){//全部熄灭LCD段
		LCDMEM[i] = 0;
		LCD_buf[i] = 16;
	}
}


//功能:初始化有关端口
//描述:对有关端口进行设置
//参数:无
//返回:无
void initial_port(void){
	//以下为看门狗定义
	WDTCTL = WDTPW + WDTHOLD;    // Stop WDT
  	
  	//以下为口定义
  	P1DIR |= BIT3;//rf power
  	P1OUT &= ~BIT3;
  	
  	P1IES |= (BIT4+BIT5);//P1.4-RF干簧管,P1.5-限位开关,下降沿触发
  	P1IE  |= (BIT4+BIT5);
  	  		
  	P2IES |= (BIT0+BIT1+BIT2+BIT5);//P2.2-按键, P2.5-校准键, P2.0,P2.1-流量
  	P2IE  |= (BIT0+BIT1+BIT2+BIT5);
  	
  	P2DIR &= ~BIT4; //P2.4--输入, 电压检测, 电压低则引脚为低,平常为高
  	  	
  	BTCTL = BTFRFQ0 + BTSSEL+BTDIV +BTIP1;  //每1秒中断16次,只作为时钟用
	IE2 |= BTIE;              // Enable BT interrupt

	LCDCTL = LCDON + LCD4MUX + LCDSG0_2;   // STK LCD 4Mux, S0-S19
  	
  	P6DIR |= (BIT0+BIT1+BIT2+BIT3+BIT4+BIT6+BIT7);//P6.0,...,P6.3输出--温度测量
	P6OUT &= ~(BIT0+BIT1+BIT2+BIT3+BIT4+BIT6+BIT7);//P6.6,P6.7-电机
		
	//TACTL = TASSEL0 + TACLR;// + ID0;      //SMCLK, TAR = 0 , 二分频
	
	//TACTL |= MC1;       //连续计数, start
	//CCTL0 |= CCIE; 		//CCR0 interrupt
	
	P2SEL |= (BIT6+BIT7);
	P3SEL =0xff;
  	P4SEL =0xff;
  	P5SEL =0xff;
  	
}


#pragma vector=BASICTIMER_VECTOR
__interrupt void INT_timer_basic(void)
{
	INT8U i;
	
		
	one_second++;
	if(one_second>=16){
		one_second=0;
		is_one_second=1;
	}
	
	for(i=0;i<8;i++){
		LCDMEM[i] = digit[LCD_buf[i]];//只管显示数字			
	}
	
	if(is_display_temperature_in)
	{
		LCDMEM[8] |= P8;//显示进水符号
		LCDMEM[9] |= S1;//显示温度符号
		if(T1>=0.01) point2; //显示小数点
	}
	if(is_display_temperature_out)
	{
		LCDMEM[8] |= P10;//显示出水符号
		LCDMEM[9] |= S1;//显示温度符号
		if(T2>=0.01) point2; //显示小数点
	}
	

	if(is_display_now){
		is_display_now=0;
		LCDCTL |= LCDON;
	}	
		
	LPM3_EXIT;
}

#pragma vector=PORT2_VECTOR
__interrupt void INT_port2(void){

  if(P2IFG & BIT2) {//键
    is_k1_key_ok=1; //键按下
  }

  P2IFG=0;
  LPM3_EXIT;
}

void delay(INT16U dd)
{
	INT16U i;
	for(i=0;i<dd;i++) _NOP();
}

void AD_sampling(INT16U * AD_temp)
{
	INT32U AD_counter=30000;
	INT32U AD_value=0;
	INT32U i;	
			
	CACTL2 = P2CA0 + P2CA1+CAF;
	CACTL1 |= CAON;
	
	P2DIR |= BIT3;
	P2OUT |= BIT3;//P2.3=1, 电容预充电	
	AD_value=0;
	while(CAOUT & CACTL2==0);//等待比较器翻转
	_DINT();
	for(i=0;i<AD_counter;i++)
	{
		if((CAOUT&CACTL2)==CAOUT) //CAOUT =1
		{
			P2OUT &= ~BIT3;//电容放电
		}
		else
		{
			P2OUT |= BIT3;//电容充电
			AD_value++;
		}
	}
	*AD_temp = AD_value;
	CACTL1 &= ~CAON;//关掉比较器
	P6OUT &= ~(BIT0+BIT1+BIT2+BIT3);//P6.4=0, 关掉4051
	P2OUT &= ~BIT3;//电容放电
	_EINT();
	//选择线全部无
}
//功能:计算温度值
//描述:由电阻计算对应的温度值
//参数:电阻值,(1000欧姆为0°C)参数范围1000~1454.072
//返回:温度值(°C),若有错则返回-1
float calc_Temperature(float R){
	float T;
	
	if((R>=1000)&&(R<=1229.388)){//0~60°C
	  T = -247.1918 + 0.23551 * R+1.1687e-005*R*R;
	  return T;
	}
	else if((R>1229.388)&&(R<=1454.072)){//60~120°C
	  T = -246.0572 + 0.23366 * R+1.2436e-005*R*R;
	  return T;
	}
	else{//出错
	  return -1;
	}
}
//32位无符号转换为BCD码,如:0xbc614e(12345678)->0x12345678
//返回字符数
INT8U long2dec(INT32U d, INT32U * p) {
	INT8U i=0, len=0;
  	INT32U temp=0;
  	
  	do {
    	temp<<=4;
    	temp |= (INT32U) (d % 10);
    	d= d / 10;
    	len++;
  	} while(d!=0);

  	(*p) =0;
  	for(i=0;i<len;i++)
  	{
  		(*p) <<=4;
  		(*p) |= (temp&0x0000000f);
  		temp >>=4;
  	}
  	
  	return len;
}

⌨️ 快捷键说明

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