单片机学习笔记 —— 温度与光照测量

  在实验板上有温度传感器和光照传感器,它们在不同温度/光照下电阻值会发生变化,通过对它们的电压值A/D转换,在经过处理,可以显示出环境温度和光照强度。

一、传感器电路

电流图

说明
Ro引脚:P1.4
Rt引脚:P1.3
当环境中的光照/温度变化时,Rop和Rt对应的电阻值会发生变化,V端的电压值将随着变化。



二、实现思路

测量光照:使用A/D转换,将每一次的A/D转换的结果累加,多次测量后取平均值。
测量温度:使用A/D转换测量每一次10位结果转换成8位AD值,再通过查找对应的表来获取温度,多次测量后取平均值。
结果显示:通过整除求余计算每一位的数值;温度显示在数码管前三位,需要判断正负;光照显示在数码管后3位。



三、程序实现

变量定义:定义引脚别名,温度/光照AD值相关变量和数码管显示相关的量。

#include "STC15F2K60S2.H"

sbit SEL0=P2^0;			//定义引脚
sbit SEL1=P2^1;
sbit SEL2=P2^2;
sbit SEL3=P2^3;

#define uint unsigned int
#define ulint unsigned long

uint time=0;				//延时
uint flag=1;				//标志位 区分光照/温度

uint l=0;						//光照采集次数
uint t=0;						//温度采集次数
ulint suml=0;				// 光照总和
ulint sumt=0;				// 温度总和

uint date_temp;
int temp=0;					//包含正负的温度值
uint abs_temp;				//温度取绝对值
uint light=0;				//光照值

uint temp_bai=0;		//温度百位
uint temp_shi=0;		//温度十位
uint temp_ge =0;		//温度个位

uint light_bai=0;		//光照百位
uint light_shi=0;		//光照十位
uint light_ge =0;		//光照个位

// 段选信号
char segtable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

// 温度值对应表

int code tempdata[]={239,197,175,160,150,142,135,129,124,120,116,113,109,107,104,101, 
					  99, 97, 95, 93, 91, 90, 88, 86, 85, 84, 82, 81, 80, 78, 77, 76, 
					  75, 74, 73, 72, 71, 70, 69, 68, 67, 67, 66, 65, 64, 63, 63, 62, 
					  61, 61, 60, 59, 58, 58, 57, 57, 56, 55, 55, 54, 54, 53, 52, 52, 
					  51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 
					  43, 43, 42, 42, 41, 41, 41, 40, 40, 39, 39, 38, 38, 38, 37, 37, 
					  36, 36, 36, 35, 35, 34, 34, 34, 33, 33, 32, 32, 32, 31, 31, 31, 
					  30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27, 26, 26, 26, 25, 25,
					  24, 24, 24, 23, 23, 23, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 
					  19, 19, 18, 18, 18, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 
					  13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 8, 7, 
					   7, 7, 6, 6,5, 5, 54,4, 3, 3,3, 2, 2, 1, 1, 1, 0, 0, -1, -1, -1, 
					  -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9, 
					  -10, -10, -11, -11, -12, -13, -13, -14, -14, -15, -16, -16, -17, 
					  -18, -19, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 
					  -30, -32, -33, -35, -36, -38, -40, -43, -46, -50, -55, -63, 361};

处理函数

void Delay(int n);     //延时函数
void weixuan(char i);  //位选的选择
void SEG_Display();    //显示温度/光照
void InitADC_temp();   //初始化温度
void InitADC_light();  //初始化光照
void date_processtemp();
void date_processlight();

void INIT()
{
	P0M1=0x00;P0M0=0xff;
	P2M1=0x00;
	P2M0=0x08;
	SEL3=0;	
	
	IE=0xa8;
	TMOD=0x10;	// 使用定时器T1
	TH1=(65535-40000)/256;
	TL1=(65535-40000)%256;
	TR1=1;		//启动定时器T1
}

void weixuan(char i)	//数码管位选的选择 5=>101
{
	SEL2=i/4;
	SEL1=i%4/2;
	SEL0=i%2;
}

void InitADC_temp()			//初始化温度ADC
{
	P1ASF=0xff;				//将P1口作为模拟功能A/D使用
	ADC_RES=0;				//寄存器ADC_RES ADC_RESL保存结果
	ADC_RESL=0;				//清零
	ADC_CONTR=0x8b;			//ADC_POWER=1 STAR=1  CHS=011,选择P1.3作为A/D输入来使用
	CLK_DIV=0x20;			//ADRJ=1
}
void InitADC_light()		//初始化光照ADC
{
	P1ASF=0xff;
	ADC_RES=0;
	ADC_RESL=0;
	ADC_CONTR=0x8c;			//CHS=100,选择P1.4作为A/D输入来使用
	CLK_DIV=0x20;
}

//取出百、十、个位
void date_processtemp()
{
	if(temp<0)
		abs_temp=-temp;
	else
		abs_temp=temp;
	temp_bai=abs_temp%1000/100;
	temp_shi=abs_temp%100/10;
	temp_ge =abs_temp%10;
}
void date_processlight()
{
	light_bai=light%1000/100;
	light_shi=light%100/10;
	light_ge =light%10;
}

数码管显示控制函数:

// 显示温度和光照
void SEG_Display() 
{
  //设置温度的位数
	if(temp<0)
	{
		P0=0;
		weixuan(0);				//正负判断
		P0=0x40;
		Delay(10);
	}
	else
	{
		P0=0;
		weixuan(0);
		P0=segtable[temp_bai];
		Delay(10);
	}
	
	P0=0;
	weixuan(1);
	P0=segtable[temp_shi];
	Delay(10);
	
	P0=0;
	weixuan(2);
	P0=segtable[temp_ge];
	Delay(10);
	
	//设置光的位数
	P0=0;
	weixuan(5);
	P0=segtable[light_bai];
	Delay(10);
	
	P0=0;
	weixuan(6);
	P0=segtable[light_shi];
	Delay(10);
	
	P0=0;
	weixuan(7);
	P0=segtable[light_ge];
	Delay(10);
}

中断函数:控制定时器中断时,初始化ADC,温度/光照采集交替进行;AD中断时,处理对应的温度/光照数据采集,控制ADC工作并处理数据

//定时器中断
void Timer1_Routine() interrupt 3	//3为定时器T1的中断编号
{
	IE=0x00;	//关闭总中断
	TR1=0;		//停止T1
	TH1=(65535-40000)/256;
	TL1=(65535-40000)%256;

	if(flag==1)
	{
		InitADC_light();		//初始化光照ADC
	}
	else
	{
		InitADC_temp();			// 初始化温度ADC
	}
	flag=-flag;		//以40000个机器周期为周期交替进行温度/光照ADC

	IE=0xa8;		//开启总中断
	TR1=1;			//启动定时器T1
}

//AD中断
void adc_isr() interrupt 5 using 1
{
	time++;
	IE=0x00;			//关闭中断
	
	if(time>2000)      	//采样次数达到1000
	{
		if(flag==1)		//执行温度
		{	
			date_temp=(sumt+t/2)/t;		//四舍五入
			temp=tempdata[date_temp-1]; //查找AD对应温度值
			sumt=0;
			t=0;
			time=0;
			date_processtemp();	
		}

		if(flag==-1)									//执行光
		{
			light=(suml+l/2)/l;					//四舍五入
			suml=0;
			l=0;
			time=0;
			date_processlight();
		}    
	}

	if(flag==1)
	{
		t++;
		date_temp=(ADC_RES*256+ADC_RESL)/4;//10位AD转8位AD值
		sumt+=date_temp;						//求t次温度AD值的和

	}
	if(flag==-1)
	{
		l++;
		suml+=ADC_RES*256+ADC_RESL;//求l次光照AD值的和
	}

	ADC_CONTR&=~0X10;  		//FLAG清零
	ADC_CONTR|=0X08;	 					 //ADC_START=1
	IE=0xa8;					 					 //打开中断
}

主函数:初始化+死循环

void main()
{
	INIT();
	while(1)
	{
		SEG_Display();
	}
}

将持续烧写到实验板中,我们就可以看到变化的温度和光照值了



完结 cheers! ??

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值