将18B20数字式传感器采集温度,并用液晶屏显示

平台:Keil 5 + STC89C52

晶振:11.0592MHZ

日期:2024-1-12

#include<reg52.h> //包含头文件

#include<intrins.h>

sbit RS = P2^7;   //定义端口 

sbit RW = P2^6;

sbit EN = P2^5;

#define DataPort P1

bit LCD_Check_Busy(void);

void LCD_Write_Com(unsigned char com);

void LCD_Write_Data(unsigned char Data);

void LCD_Clear(void);

void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);

void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);

void LCD_Init(void);


#define uint8 	unsigned char

#define uint16 	unsigned int
	uint16 temp;


uint8 code STR1[] = "当前温度为:";

uint8 code STR2[] = "°C";

uint8 *p;									//指针变量,存储数组元素地址

sbit DQ  = P3^7;		    				//DS18B20的数据接口

#define nops();  {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令

void delay_11us(uint16 n);					//函数声明

void delay_ms(uint16 n);

void ds18b20_reset(void);

void write_byte(uint8 val);

uint8 read_byte(void);

void start_convert(void);

uint16 read_temp(void);

void uart_init(void);

void UART_Send_Byte(uint8 dat);

void UART_Send_STR(void);

void UART_Send_Dat(uint8 dat);

/***************************************************

*								us延时子函数

*						 n=1时,约为11us

****************************************************/

void delay_11us(unsigned char n)
{

	do {

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

    } while (--n);

}

/***************************************************

*								ms延时子函数

*						 n=1时,约为1ms

****************************************************/

void delay_ms(uint16 n)

{

	uint8 m=120;

	while (n--)

		while (m--);

}

/***************************************************

*								DS18B20复位子函数

*						 总线拉低550us,释放66us

****************************************************/

void ds18b20_reset(void)

{

	bit flag=1;

	while (flag)				//判断初始化是否成功

	{

		while (flag)			//判断DS18B20是否给出反馈

	 	{

 			DQ = 1;

			delay_11us(1);	//高电平约11us

 			DQ = 0;

 			delay_11us(50); //低电平550us

 			DQ = 1; 

 			delay_11us(6);  //释放66us

 			flag = DQ;			//总线状态采样

   	}

		delay_11us(50);   //延时550us

		flag = ~DQ;				//总线状态采样

	}

	DQ=1;

}

/***************************************************

*							向总线写入一个字节

****************************************************/

void write_byte(uint8 val)

{

	uint8 i;

	for (i=0; i<8; i++)

	{

		DQ = 1;								//写时隙准备工作

		_nop_();

		DQ = 0;								//告诉DS18B20,准备采样

		nops(); 							//4us

		DQ = val & 0x01;      //最低位移出

		delay_11us(6);        //66us

		val >>= 1;          	//右移一位

	}

	DQ = 1;

	delay_11us(1);  

}

/***************************************************

*					    	从总线读出一个字节

****************************************************/

uint8 read_byte(void)

{

	uint8 i, value=0;

	for (i=0; i<8; i++)

	{

		DQ=1;								//读时隙准备工作

		_nop_();

		value >>= 1;

		DQ = 0;							//告诉DS18B20,准备发送

		nops();   					//4us

		DQ = 1;							//释放总线

		nops();   					//4us 

		if (DQ)							//0和1的判断

			value|=0x80;

		delay_11us(6);           //66us

	}

	DQ=1;

	return(value);				//返回采集到的数据

}

/***************************************************

*								温度转换子函数

*						根据操作顺序,发出转换命令

****************************************************/

void start_convert(void)

{

	ds18b20_reset();

	write_byte(0xCC); 		// 发Skip ROM命令

	write_byte(0x44); 		// 发转换命令

}

/***************************************************

*								温度读取子函数

*						根据操作顺序,读取温度值

****************************************************/

uint16 read_temp(void)

{

	uint8 temp_data[2]; 			// 读出温度暂放

	uint16 temp;



	ds18b20_reset();  				// 复位

	write_byte(0xCC); 				// 发Skip ROM命令

	write_byte(0xBE); 				// 发读命令

	temp_data[0]=read_byte();  //温度低8位

	temp_data[1]=read_byte();  //温度高8位

	temp = temp_data[1];

	temp <<= 8;

	temp |= temp_data[0];

	return temp;

}

/***************************************************

*								UART初始化子函数

*						定时器1,工作方式2,波特率9600

****************************************************/

void uart_init(void)

{

	TMOD = 0x20;        // 定时器1工作在方式2

	SCON = 0x50;        // 8位uart,允许串行接受

	TH1 = 0xFD;					//设置定时器初值

	TL1 = 0xFD;					//设置定时器初值

	TR1 = 1;						//启动定时器1

}

/***************************************************

*								UART发送一个字节

****************************************************/

void UART_Send_Byte(uint8 dat)

{

	SBUF = dat;					//送入缓冲寄存器

	while (TI == 0);		//等待发送完成

	TI = 0;

}

/***************************************************

*								UART发送一串字符

****************************************************/

void UART_Send_STR(void)

{

	while(*p != '\0')

	{

		SBUF = *p;					//送入缓冲寄存器

		while (TI == 0);		//等待发送完成

		TI = 0;

		p++;								//地址加一

	}

}

/***************************************************

*								数值转换子函数

*						将要发送的数转换为ASCII码

****************************************************/

void UART_Send_Dat(uint8 dat)

{

	UART_Send_Byte(dat/10 + '0');		//发送十位数

	UART_Send_Byte(dat%10 + '0');		//发送个位数

}









/***************************************************

*								判忙子函数

*			读取状态字的STA7位来判断液晶是否忙碌

****************************************************/

bit LCD_Check_Busy(void) 

{ 

	unsigned char state;

	DataPort= 0xFF; 

	EN = 0;

	RS = 0; 

	RW = 1;

	_nop_(); 

	EN = 1;

	state=DataPort;

	_nop_(); 

	EN = 0;

	return (bit)(state&0x80);

}

/***************************************************

*								写入命令子函数

*			先判断液晶是否忙碌,不忙则写入

****************************************************/

void LCD_Write_Com(unsigned char com) 

{  

	while(LCD_Check_Busy()); //忙则等待

	EN = 0;

	RS = 0;

	RW = 0;

	_nop_();

	EN = 1;

	DataPort= com; 

	_nop_(); 

	EN = 0;

}

/***************************************************

*								写入数据子函数

*			先判断液晶是否忙碌,不忙则写入

****************************************************/

void LCD_Write_Data(unsigned char Data) 

{ 

	while(LCD_Check_Busy()); //忙则等待

	EN = 0;    //默认低电平

	RS = 1; 

	RW = 0;

	_nop_();

	EN = 1;

	DataPort= Data; 

	_nop_();

	EN = 0;

}

/***************************************************

*								清屏子函数

*			通过调用写入命令子函数来实现

****************************************************/

void LCD_Clear(void) 

{ 

	LCD_Write_Com(0x01); 



}

/***************************************************

*						     写入字符串子函数

*			         使用字符型指针做为形参

****************************************************/

void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 

{     

	if (y == 0)      

		LCD_Write_Com(0x80 + x);     //表示第一行

	else     

		LCD_Write_Com(0xC0 + x);     //表示第二行   

	while (*s)                      //  “/0”

	{     

	LCD_Write_Data( *s);     

	s ++;     

	}

}

/***************************************************

*						     写入字符子函数

*			         先输入地址,后输入字符

****************************************************/

void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 

{     

	if(y == 0)   

		LCD_Write_Com(0x80 + x);  

	else   

		LCD_Write_Com(0xC0 + x);       

	LCD_Write_Data( Data);  

}

/***************************************************

*						     初始化子函数

*			         参照1602datasheet

****************************************************/

void LCD_Init(void) 

{

	

	LCD_Write_Com(0x38);  

	LCD_Write_Com(0x08);    /*显示关闭*/ 

	LCD_Write_Com(0x01);    /*显示清屏*/ 

	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 

	LCD_Write_Com(0x0C);    /*显示开及光标设置*/

}

//主程序

main()

{

	uint16 wendu;

	uart_init();								//串口初始化

	while (1)

	{

		start_convert();					//启动温度转换

		delay_ms (1000); 					// 延时1秒

		wendu=read_temp();				//读取暂存器中的温度数据

		if (wendu > 60000)				//判断温度正负

		{
			LCD_Write_Char(5,1,'-');
			UART_Send_Byte('-');		//添加负号

			wendu = ~wendu;					//按位取反

			wendu++;								//加一,得到补码

		}
		temp=wendu;
		a[0]=temp/10;
		a[1]=temp%10;
		wendu >>= 4;							//忽略掉小数位

		LCD_Init(); 		//屏幕初始化

		LCD_Clear();		//清屏

		LCD_Write_String(0,0,"temperture");
		LCD_Write_Char(6,1,wendu/10+'0');
		LCD_Write_Char(7,1,wendu%10+'0');
		LCD_Write_String(9,1,"oc");

	}

}

 

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值