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

📄 main.c

📁 单片机C8051F221读取DS18B20温度值
💻 C
字号:
#include <c8051F200.h>
#include <INTRINS.H>

sbit	TEMPERCON=P2^3;
sbit	WDI=P2^4;
sbit	DQ=P2^5;
sbit	LCD_CS=P1^7;
sbit	LCD_RD=P1^6;
sbit	LCD_WR=P1^5;
sbit	LCD_DA=P1^4;

bit 	FLG_DS18B20_RET;
bit		Temper_Flag=1;
float 	Temperature=0.0;
unsigned char lcd_dat_1;
unsigned char lcd_dat_2;

//*************************************************************************************
//函数名称;Delay_1us()
//函数功能:执行 12*cnt+1 条单指令,对于C8051F221晶振频率为12M的情况下,延时1us乘以cnt
//输入参数;unsigned char cnt
//返回参数:无	
//*************************************************************************************
void Delay_1us(unsigned char cnt)
{
	unsigned char i;
	for (i = cnt; i > 0; i--)
	{
		_nop_();
		_nop_();
		_nop_();
	}
}
//************************************************************************************
//函数名称;Delay_4ms()
//函数功能:执行 4000*cnt+1 条单指令,对于C8051F221晶振频率为12M的情况下,延时4ms乘以cnt
//输入参数;unsigned char cnt
//返回参数:无	
//************************************************************************************
void Delay_4ms(unsigned char cnt)
{//(5k+4)j+9
	unsigned char  i,j,k;
	for(i=cnt;i>0;i--)
	{	
		for(j=224;j>0;j--)
		{	
			for(k=42;k>0;k--)
			WDI=~WDI;
			_nop_();
			_nop_();
		}
	}
}

/**************************************************************************************
函数名称;C8051F221_Init()
函数功能:寄存器及端口初始化
输入参数;无
返回参数:无	
**************************************************************************************/
void C8051F221_Init(void)
{	

	WDTCN=0xDE;			//禁止看门狗		
	WDTCN=0xAD;

	OSCXCN |= 0x67;     // External Oscillator is an external
                        // crystal (no divide by 2 stage)
//	Delay_4ms(250);
//	Delay_4ms(250);	
    while(!(OSCXCN & 0x80));    // Wait for crystal osc. to settle	
    OSCICN = 0x88;      // select external oscillator as SYSCLK
                        // source and enable missing clock
                        // detector	
      
	PRT0MX |= 0x00;		//定时器1使能	 
	PRT1MX |= 0x00;		//SYSCLK输出、比较器使能
	PRT2MX |= 0x00;	 	//端口弱上拉、SPI总线使能:P1口弱上拉禁止

	PRT0CF |= 0x00;		//设置漏极开路方式
	PRT1CF |= 0x00;
	PRT2CF |= 0x08;		//P2.3为推挽方式

	P0MODE |= 0xff;		//数字输入使能,模拟输入禁止
	P1MODE |= 0xff;
	P2MODE |= 0xff;
	
	//REF0CN |= 0x03;		//选择VDD为VREF源
  
}

/**************************************************************************************
函数名称;DS18B20_Init()
函数功能:DS18B20初始化
输入参数;无
返回参数:无
全局变量:FLG_DS18B20_RET 为1初始化失败,为0初始化成功	
**************************************************************************************/
void DS18B20_Init(void)		
{ 
 DQ = 0;    			// 单片机将DQ拉低
 Delay_1us(250);		// 精确延时大于480us,小于960us 
 Delay_1us(250);
 DQ = 1;    			// 释放总线
 Delay_1us(30);			// DS18B20检测到高后,等待15-60us将总线拉低,保持60-240us 
 FLG_DS18B20_RET=DQ;    // 稍做延时后 如果FLG_DS18B20_RET=0则初始化成功,否则初始化失败 
 Delay_1us(250);    	// 精确延时 大于 240us 		 
}

/**************************************************************************************
函数名称;DS18B20_ReadOnebit()
函数功能:DS18B20读1位
输入参数;无
返回参数:dat_bit
全局变量:无
**************************************************************************************/ 
bit DS18B20_ReadOnebit(void)
{
	bit dat_bit;
	DQ = 0; 			// 读时序开始
  	Delay_1us(1);		// 延时1us后释放总线	
  	DQ = 1;	
	Delay_1us(8);	    // 推荐将采样时间延时到15us的后期
	dat_bit=DQ;
	Delay_1us(60);		// 整个读时序至少保持时间60us
	return(dat_bit);
}

/**************************************************************************************
函数名称;DS18B20_ReadOneChar()
函数功能:DS18B20读1个字节
输入参数;无
返回参数:CharDat
全局变量:无
**************************************************************************************/ 
unsigned char DS18B20_ReadOneChar(void)
{
	unsigned char i,Onebit,CharDat=0;
	
	for (i=8;i>0;i--)
 	{	
		Onebit=DS18B20_ReadOnebit();
		CharDat=((Onebit<<7)|(CharDat>>1));
	}
	return(CharDat);		
}

/**************************************************************************************
函数名称;DS18B20_WriteOneChar()
函数功能:DS18B20写1个字节
输入参数;unsigned char dat
返回参数:无
全局变量:无
**************************************************************************************/
void DS18B20_WriteOneChar(unsigned char dat)
{
 unsigned char i;
 bit tmp;
 for (i=8; i>0; i--)
 {
	tmp=dat&0x01;
	dat=dat>>1;
	if(tmp)
	{	//写“1”
		DQ = 0;			// 写时序开始  					
  		Delay_1us(8);		// 15us内释放总线
  		DQ = 1;			// 写"1"  
  		Delay_1us(60);		// 将写"1"保持至少60us    
 	}
	else
	{	//写"0"
		DQ = 0;			// 写时序开始
		Delay_1us(60);		// 将写"0"保持60us~120us
		DQ = 1;
		Delay_1us(1);
	}		
 }  
} 

/**************************************************************************************
函数名称;DS18B20_WriteOneChar()
函数功能:读取DS18B20温度值
输入参数;unsigned char dat
返回参数:无
全局变量:Temperature;   Temper_Flag=1温度为零上,否则为零下
**************************************************************************************/ 
void DS18B20_ReadTemperature(void)
{ 
 	unsigned char a=0;
 	unsigned char b=0;
 	unsigned char c=0; 
 	unsigned char d=0;
	unsigned char e=0; 
	unsigned int  t=0;
/*
    DS18B20_Init(); 
 	DS18B20_WriteOneChar(0xCC); // 跳过读序号列号的操作
 	DS18B20_WriteOneChar(0x4E);	// 写暂存器
 	DS18B20_WriteOneChar(0xff);	// 写TH寄存器
 	DS18B20_WriteOneChar(0xff);	// 写TL寄存器
 	DS18B20_WriteOneChar(0xff);	// 写配置寄存器
 	DS18B20_WriteOneChar(0x48);	// 拷贝暂存器内容到eerprom
*/
 	DS18B20_Init();
	WDI=~WDI;
 	DS18B20_WriteOneChar(0xCC); // 跳过读序号列号的操作
 	DS18B20_WriteOneChar(0x44); // 启动温度转换	
	WDI=~WDI;
 	Delay_4ms(250);
	//Delay_4ms(250);
	//Delay_4ms(250);	
	//Delay_4ms(250);
	WDI=~WDI;
	DS18B20_Init();
    DS18B20_WriteOneChar(0xCC); //跳过读序号列号的操作
 	DS18B20_WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
 	a=DS18B20_ReadOneChar();	// 读温度低八位
 	b=DS18B20_ReadOneChar();	// 读温度高八位
	c=DS18B20_ReadOneChar();
	d=DS18B20_ReadOneChar();
	e=DS18B20_ReadOneChar();
	
	DS18B20_Init();
 	t=b;
 	t<<=8;
 	t=t|a;
	if((b<8)||(b!=255))
		{
			Temper_Flag=1;				//温度值大于零
 			Temperature=t*0.0625;  	
		}
	else
		{
			Temper_Flag=0;				//温度值小于零
 			Temperature=((~t)+1)*0.0625;  
		}
}
/**************************************************************************************
函数名称;LCD_WrCom()
函数功能:向LCD写入命令--LCM046
输入参数;unsigned char command
返回参数:无
全局变量:无
**************************************************************************************/
void LCD_WrCom(unsigned char command)
{	
		unsigned char i,tmp;
		tmp = command;		
		LCD_CS=0;
		Delay_1us(30);

		LCD_WR=0;		//写入"100"
		LCD_DA=1;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);
		
		LCD_WR=0;		
		LCD_DA=0;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);
		
		LCD_WR=0;	
		LCD_DA=0;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);
		
		CY=0;
		for(i=9;i>0;i--)//写入命令
			{				
				LCD_WR=0;		
				if(tmp&0x80)
					LCD_DA=1;
				else
					LCD_DA=0;		
				Delay_1us(6);
				LCD_WR=1;
				Delay_1us(6);
				tmp=tmp<<1;
			}
		LCD_DA=1;
		LCD_WR=1;
		LCD_CS=1;
		Delay_1us(60);
		
} 
/**************************************************************************************
函数名称;LCD_Add_Dat()
函数功能:向LCD写入地址、数据
输入参数;unsigned char command
返回参数:无
全局变量:无
备注:    格式;101  0 A4 A3 A2 A1 A0  D0 D1 D2 D3
**************************************************************************************/	
void LCD_Add_Dat(unsigned char add,unsigned char dat)
{
		unsigned char i,j,tmp1,tmp2;
		tmp1=add;
		tmp2=dat;	
		LCD_CS=0;
		Delay_1us(15);
		LCD_WR=0;				//写入"101"
		LCD_DA=1;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);
		
		LCD_WR=0;		
		LCD_DA=0;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);
		
		LCD_WR=0;		
		LCD_DA=1;		
		Delay_1us(6);
		LCD_WR=1;
		Delay_1us(6);			
		
		for(i=6;i>0;i--)		//写入5位地址
			{				
				LCD_WR=0;						
				if(tmp1&0x20)
					LCD_DA=1;
				else
					LCD_DA=0;		
				Delay_1us(6);
				LCD_WR=1;
				Delay_1us(6);
				tmp1=tmp1<<1;
			}
		Delay_1us(6);
		for(j=4;j>0;j--)		//写入4位数据
			{				
				LCD_WR=0;		
				if(tmp2&0x01)
					LCD_DA=1;
				else
					LCD_DA=0;		
				Delay_1us(6);
				LCD_WR=1;
				Delay_1us(6);
				tmp2=tmp2>>1;
			 }

		LCD_DA=1;
		LCD_WR=1;
		LCD_CS=1;
		Delay_1us(60);
}	
//LCD初始化
/**************************************************************************************
函数名称;LCD_Init()
函数功能:LCD初始化
输入参数;无
返回参数:无
全局变量:无
**************************************************************************************/
void LCD_Init(void)
{
		LCD_CS=1;
		LCD_WR=1;
		LCD_RD=1;
		Delay_1us(250);

		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);
		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);

		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);
		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);

		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);
		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);

		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);
		LCD_CS=0;
		Delay_1us(60);
		LCD_CS=1;
		Delay_1us(20);

		LCD_WrCom(0x29);	//初始化命令
		LCD_WrCom(0x18);	//内部RC
		LCD_WrCom(0x01);	//开振荡器
		LCD_WrCom(0x03);	//开显示器

		LCD_Add_Dat(0x00,0x00);		//不显示
		LCD_Add_Dat(0x01,0x00);
		LCD_Add_Dat(0x02,0x00);
		LCD_Add_Dat(0x03,0x00);
		LCD_Add_Dat(0x04,0x00);
		LCD_Add_Dat(0x05,0x00);
		LCD_Add_Dat(0x06,0x00);
		LCD_Add_Dat(0x07,0x00);
	
} 	
/**************************************************************************************
函数名称;Lcd_Hex()
函数功能:将要显示的数值转换为LCD输入的十六进制
输入参数;unsigned char lcd_dat
返回参数:无
全局变量:lcd_dat_1; lcd_dat_2
**************************************************************************************/
void Lcd_Hex(unsigned char lcd_dat)
{
		switch(lcd_dat)
		{
			case 1:
			lcd_dat_1=0x00;
			lcd_dat_2=0x05;
			break;

			case 2:
			lcd_dat_1=0x05;
			lcd_dat_2=0x0b;
			break;
			
			case 3:
			lcd_dat_1=0x01;
			lcd_dat_2=0x0f;
			break;

			case 4:
			lcd_dat_1=0x02;
			lcd_dat_2=0x07;
			break;

			case 5:
			lcd_dat_1=0x03;
			lcd_dat_2=0x0e;
			break;

			case 6:
			lcd_dat_1=0x07;
			lcd_dat_2=0x0e;
			break;

			case 7:
			lcd_dat_1=0x01;
			lcd_dat_2=0x05;
			break;

			case 8:
			lcd_dat_1=0x07;
			lcd_dat_2=0x0f;
			break;

			case 9:
			lcd_dat_1=0x03;
			lcd_dat_2=0x0f;
			break;

			case 0:
			lcd_dat_1=0x07;
			lcd_dat_2=0x0d;
			break;
		}
}

/**************************************************************************************
函数名称;Temper_showed()
函数功能:LCD显示温度值
输入参数;无
返回参数:无
全局变量:lcd_dat_1; lcd_dat_2; Temperature; Temper_Flag
**************************************************************************************/
void Temper_showed(void)
{
	unsigned int tmp;
	unsigned char lcd_dat_tmp; 	
	
	tmp=(int)(Temperature*10);			//将要显示的数变为整数取出
	if(Temperature<100)
	{			
		if(!Temper_Flag)
		{
			LCD_Add_Dat(0x00,0x00);		//显示负号
			LCD_Add_Dat(0x01,0x02);
		}
		else
		{
			LCD_Add_Dat(0x00,0x00);		//不显示
			LCD_Add_Dat(0x01,0x00);
		}
		
		lcd_dat_tmp=tmp/100;			//取出十位数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x02,lcd_dat_1);	//显示十位
		LCD_Add_Dat(0x03,lcd_dat_2);

		lcd_dat_tmp=(tmp%100)/10;		//取出个位数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x04,lcd_dat_1);	//显示个位
		LCD_Add_Dat(0x05,lcd_dat_2);	

		lcd_dat_tmp=tmp%10;				//取出小数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x06,lcd_dat_1|0x08);//显示小数和小数点
		LCD_Add_Dat(0x07,lcd_dat_2);		
	}
	else
	{
		lcd_dat_tmp=tmp/1000;			//取出百位数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x00,lcd_dat_1);	//显示百位
		LCD_Add_Dat(0x01,lcd_dat_2);

		lcd_dat_tmp=(tmp%1000)/100;		//取出十位数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x02,lcd_dat_1);	//显示十位
		LCD_Add_Dat(0x03,lcd_dat_2);	

		lcd_dat_tmp=((tmp%1000)%100)/10;//取出个位数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x04,lcd_dat_1);	//显示个位
		LCD_Add_Dat(0x05,lcd_dat_2);

		lcd_dat_tmp=tmp%10;				//取出小数
		Lcd_Hex(lcd_dat_tmp);
		LCD_Add_Dat(0x06,lcd_dat_1|0x08);//显示小数和小数点
		LCD_Add_Dat(0x07,lcd_dat_2);
	}	
}

void main(void)
{	
	unsigned char i;
			  	
	C8051F221_Init();
	TEMPERCON = 0;
	WDI=0;
	LCD_Init();		
	WDI=~WDI;

	while(1)
	{	
		WDI=~WDI;	
		DS18B20_ReadTemperature();
		WDI=~WDI;
		Temper_showed();
		WDI=~WDI;
		if(Temperature>37)
		{
			TEMPERCON = 1;

			while(Temperature>35)
				{
					//延时180s
					for(i=4;i>0;i--)
						{	WDI=~WDI;
							Delay_4ms(250);
							WDI=~WDI;
						}
					DS18B20_ReadTemperature();
					WDI=~WDI;
					Temper_showed();
				}
			TEMPERCON = 0;
		}	
		else
			TEMPERCON = 0;
		
		//延时180s
		for(i=4;i>0;i--)
			{
				WDI=~WDI;
				Delay_4ms(250);
				WDI=~WDI;
			}
	 }	

}

⌨️ 快捷键说明

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