【【51单片机的温度识别】】

news2024/11/24 18:27:47

51单片机的温度识别

这么热的天,再离我远一点

DS18B20温度读取
温度报警
我们这里对于单总线 也仿照I2C 总线的模样
在这里插入图片描述
以下是我们实现的onewire.c文件

#include <REGX52.H>
//第一步从原理图触发先定义端口

sbit OneWire_DQ=P3^7;

//第一步初始化

unsigned char OneWire_Init(void)

    //初始化主机将总线拉低至少480us 然后释放总线
    //等待15-60us 存在的从机会拉低总线60-240us 以响应
    //之后从机释放主机
    {
        unsigned char i;
        unsigned char AckBit;
    //因为我们再执行任何状态都可以通过初始化去打断他
        //所以这里先将端口置为1
        OneWire_DQ=1;
        OneWire_DQ=0;
        //因为delay微秒很难控制
        //我们delay内部的while什么的跳转也需要时间 之前我们默认调准不需要时间
        //void Delay500us()        //@11.0592MHz
    i = 227;while (--i);
//上面这段我是用软件算出来的延迟500微妙
     OneWire_DQ=1;
        
        //接下来处理等待15-60us
        //江科大说延迟70us 行那我就按照他的逻辑延迟70
    i = 29;while (--i);
    //因为我们已经放手了,接下来直接读出状态就可以了
    AckBit=OneWire_DQ;
        i = 227;while (--i);
        //再delay 500us这个程序正好走完了
        return AckBit;
}
    

//第二步写发送模块

void OneWire_SendBit(unsigned char Bit)
    //发送一位 主机将总线拉低60-120us,然后释放总线 表示发送0
//主机将总线拉低1-15us,然后释放总线,表示发送1 
//从机将在总线拉低30us后 (这个30是典型值) 读取电平 整个时间片应大于60us
{
    unsigned char i;
    OneWire_DQ=0;
    i = 3;while (--i);  //Delay10us 
    OneWire_DQ=Bit;
    i = 22;while (--i); // delay50us
    OneWire_DQ=1;
    //释放掉就是置1 的意思
}
    



//第三步 接收模块
unsigned char OneWire_ReceiveBit(void)
    //主机将总线拉低1-15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾)
//读取为低电平则为接收0 ,读取为高电平则为接收1 ,整个时间片应大于60us
{
    unsigned char Bit;
    unsigned char i;
    OneWire_DQ=0;
    i = 1;while (--i);  //delay 5us
    OneWire_DQ=1;    //释放掉总线
    i = 1;while (--i);  //delay 5us
    Bit=OneWire_DQ;
    i = 22;while (--i); // delay50us
    return Bit;    
}




//第四步写发送一个字节和接受一个字节的模块
void OneWire_SendByte(unsigned char Byte)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        OneWire_SendBit(Byte&(0x01<<i));    
    }

}


//第五步接收字节
unsigned char OneWire_ReceiveByte(void)
{
    unsigned char i;
    unsigned char Byte;
    for(i=0;i<8;i++)
    {
        if(OneWire_ReceiveBit())
        {
            Byte|=(0x01<<i) ;
        }
    }
    return Byte;
}

下面是实现的DS18B20.c

#include <REGX52.H>
#include"OneWire.h"

#define DS18B20_SKIP_ROM      0xCC
#define DS18B20_CONVERT_T      0x44
#define DS18B20_READ_SCRATCHPAD 0xBE






//DS18B20 的基本操作流程
//初始化 : 从机复位,主机判断从机是否响应
//ROM操作 : ROM指令+本指令需要的读写操作
//功能操作 : 功能指令+本指令需要的读写操作

//本次想要实现的功能有
//温度变换 : 初始化->跳过ROM->开始温度变换

//温度读取: 初始化->跳过ROM->读暂存器-> 连续的读操作



//这上面都是一些指令
//温度变换的过程是这样的 初始化  跳过ROM 开始温度变化
void DS18B20_ConvertT(void)
{
    OneWire_Init();
    OneWire_SendByte(DS18B20_SKIP_ROM);
    OneWire_SendByte(DS18B20_CONVERT_T);
}




//温度读取: 初始化->跳过ROM->读暂存器-> 连续的读操作
float DS18B20_ReadT(void)
{
    unsigned char TLSB,TMSB;
    int Temp;
    float T;
    OneWire_Init();
    OneWire_SendByte(DS18B20_SKIP_ROM);
    OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
    //接下来处理的是连续的读操作
    //一旦我们发送了这个指令之后总线的控制权就会给到从机了
    
    
    //这是两个温度字节的数据
    TLSB=OneWire_ReceiveByte();
    TMSB=OneWire_ReceiveByte();
    Temp=(TMSB<<8)|TLSB;
    T=Temp/4.0;
    return T;
}

下面是完整的全部代码

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"

float T;

void main()
{
	DS18B20_ConvertT();		//上电先转换一次温度,防止第一次读数据错误
	Delay(1000);			//等待转换完成
	LCD_Init();
	LCD_ShowString(1,1,"Temperature:");
	while(1)
	{
		DS18B20_ConvertT();	//转换温度
		T=DS18B20_ReadT();	//读取温度
		if(T<0)				//如果温度小于0
		{
			LCD_ShowChar(2,1,'-');	//显示负号
			T=-T;			//将温度变为正数
		}
		else				//如果温度大于等于0
		{
			LCD_ShowChar(2,1,'+');	//显示正号
		}
		LCD_ShowNum(2,2,T,3);		//显示温度整数部分
		LCD_ShowChar(2,5,'.');		//显示小数点
		LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示温度小数部分
	}
}

Delay.c

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

DS18B20.c

#include <REGX52.H>
#include "OneWire.h"

//DS18B20指令
#define DS18B20_SKIP_ROM			0xCC
#define DS18B20_CONVERT_T			0x44
#define DS18B20_READ_SCRATCHPAD 	0xBE

/**
  * @brief  DS18B20开始温度变换
  * @param  无
  * @retval 无
  */
void DS18B20_ConvertT(void)
{
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_CONVERT_T);
}

/**
  * @brief  DS18B20读取温度
  * @param  无
  * @retval 温度数值
  */
float DS18B20_ReadT(void)
{
	unsigned char TLSB,TMSB;
	int Temp;
	float T;
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
	TLSB=OneWire_ReceiveByte();
	TMSB=OneWire_ReceiveByte();
	Temp=(TMSB<<8)|TLSB;
	T=Temp/16.0;
	return T;
}

DS18B20.h

#ifndef __DS18B20_H__
#define __DS18B20_H__

void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);

#endif

LCD1602.c

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/786429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

商城-学习整理-基础-前端(四)

目录 一、技术栈介绍二、ES61、简介2、什么是ECMAScript3、ES6 新特性1、let 声明变量2、const 声明常量&#xff08;只读变量&#xff09;3、解构表达式1&#xff09;数组解构2&#xff09;对象解构 4、字符串扩展1&#xff09;、几个新的 API2&#xff09;、字符串模板 5、函…

跨洋消息队列CKafka

背景 跨洋消息队列CKafka&#xff0c;是腾讯出品开源消息队列组件&#xff0c;为了解决客户跨地域容灾、冷备的诉求跨地域秒级准实时数据同步而开源的腾讯云中间件。 整体架构图 数据同步主要流程 Connect 集群初始化 Connect Task&#xff0c;每个 Task 会新建多个 Worker C…

3D元宇宙游戏,或许能引爆新的文娱消费增长点

从去年开始&#xff0c;在互联网上&#xff0c;一个名为【神念无界-源起山海】的元宇宙游戏项目火了。除了可以在游戏内体验独战、团队式作战等3D古风经典游戏场景和玩法&#xff0c;还有钓鱼增加能量、情侣姻缘一线牵&#xff0c;结婚等多元化逼真效果与玩法&#xff0c;这令很…

第118天:免杀对抗-二开CS上线流量特征Shellcode生成机制反编译重打包(上)

知识点 #知识点&#xff1a; 1、CS-表面特征消除 2、CS-HTTP流量特征消除 3、CS-Shellcode特征消除#章节点&#xff1a; 编译代码面-ShellCode-混淆 编译代码面-编辑执行器-编写 编译代码面-分离加载器-编写 程序文件面-特征码定位-修改 程序文件面-加壳花指令-资源 代码加载面…

opencv-21 alpha 通道详解(应用于 图像增强,合成,蒙版,特效 等)

什么是alpha 通道&#xff1f; Alpha通道是计算机图形学中用于表示图像透明度的一种通道。在一个图像中&#xff0c;通常会有三个颜色通道&#xff1a;红色&#xff08;R&#xff09;、绿色&#xff08;G&#xff09;、蓝色&#xff08;B&#xff09;&#xff0c;它们合在一起…

将Parasoft和ChatGPT相结合会如何?

ChatGPT是2023年最热门的话题之一&#xff0c;是OpenAI训练的语言模型。它能够理解和生成自然语言文本&#xff0c;并接受过大量数据的训练&#xff0c;包括用各种编程语言编写的许多开源项目的源代码。 软件开发人员可以利用大量的知识库来协助他们的工作&#xff0c;因为它具…

网络安全高级课笔记1

HTML字符编码/HTML实体编码 html实体编码 unicode urlcode 在字符的十六进制前加百分号&#xff08;%&#xff09;&#xff0c;用于浏览器的网址输入框 utf-8 字符数字表示法 HTML允许使用Nuicode码点表示字符&#xff0c;浏览器会自动将码点转成对应的字符。 字符的码点表…

vtk能否被OpenGL和DirectX取代?

VTK&#xff08;Visualization Toolkit&#xff09;是一个强大的开源可视化库&#xff0c;用于处理和呈现各种科学数据。它建立在OpenGL和DirectX等底层图形库之上&#xff0c;提供了高级的可视化功能和算法。虽然OpenGL和DirectX可以用于图形渲染和实时图形处理&#xff0c;但…

数据结构--线性表2-1

目录 一、线性结构的定义 二、线性表的表示 三、顺序表的实现&#xff08;或操作&#xff09; 1、修改&#xff1a; 2、插入&#xff1a; 四、顺序表的运算效率分析&#xff1a;时间效率分析&#xff1a; 一、线性结构的定义 若结构时非空有限集&#xff0c;则有且仅有一个…

python爬虫基础入门——利用requests和BeautifulSoup

(本文是自己学习爬虫的一点笔记和感悟) 经过python的初步学习,对字符串、列表、字典、元祖、条件语句、循环语句……等概念应该已经有了整体印象,终于可以着手做一些小练习来巩固知识点,写爬虫练习再适合不过。 1. 网页基础 爬虫的本质就是从网页中获取所需的信息,对网…

优化帮助与支持中心,提升客户满意度

在竞争激烈的商业环境中&#xff0c;提供良好的客户体验和有效的支持服务是企业获得成功的关键因素之一。优化帮助与支持中心的设计和运营对于提升客户满意度至关重要。本文将探讨如何通过优化帮助与支持中心来提升客户满意度&#xff0c;并为企业带来更多的商业机会。 提供多…

2023年深圳杯数学建模 A题 影响城市居民身体健康的因素分析

以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病&#xff08;以下简称慢性病&#xff09;已经成为影响我国居民身体健康的重要问题。随着人们生活方式的改变&#xff0c;慢性病的患病率持续攀升。众所周知&#xff0c;健康状况与年龄、饮食习惯、…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 25 日论文合集)

文章目录 一、分割|语义相关(17篇)1.1 Semi-Supervised Medical Image Segmentation with Co-Distribution Alignment1.2 CTVIS: Consistent Training for Online Video Instance Segmentation1.3 SL: Stable Learning in Source-Free Domain Adaption for Medical Image Segme…

16_LinuxLCD驱动

目录 Framebuffer设备 LCD驱动简析 LCD驱动程序编写 LCD屏幕参数节点信息修改 LCD 屏幕背光节点信息 使能Linux logo显示 设置LCD作为终端控制台 Framebuffer设备 先来回顾一下裸机的时候LCD驱动是怎么编写的,裸机LCD驱动编写流程如下: 1.初始化I.MX6U的eLCDIF控制器,…

【代码随想录day19】找树左下角的值

题目 思路 这题最直观的方法就是用层序遍历&#xff0c;记录一下每一层的左边第一个节点&#xff0c;这样整个层序遍历一遍就能找到最后一行最左边的节点。这里要注意最左边的节点不一定是父节点的左子节点&#xff01;&#xff01;&#xff01;如果最后一行没有左子节点&…

M5ATOMS3基础01按键

initinputoutput Linux环境Arduino IDE中配置ATOM S3 示例 官方示例代码&#xff1a; /* ******************************************************************************* * Copyright (c) 2022 by M5Stack * Equipped with M5AtomS3 sample source c…

Redis过期策略和内存淘汰策略

过期策略 过期策略是指Redis设置过期时间且key已经到达过期时间时删除该key&#xff0c;一般有定期删除和惰性删除&#xff1b; 定期删除是指每隔固定时间扫描key&#xff0c;对已经过期的key做清除操作&#xff1b; 定期删除时并不会实际对key做全量扫描&#xff0c;而是随机…

数字时代下CIO们如何做到业务增长和安全“双手抓”

7月22日&#xff0c;由福建信息主管(CIO)网主办的品牌企业业务增长与CIO进化之道暨福建CIO网20周年&#xff08;厦门&#xff09;产业数字化供需见面会在厦门顺利举办。 作为国内云原生安全领导厂商&#xff0c;安全狗也收到邀请出席此次活动。 厦门服云信息科技有限公司&…

Python实战案例:轻松采集微博评论,揭示网络舆论热点!

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 开发环境: python 3.8: 解释器 pycharm: 代码编辑器 模块使用: requests: 发送请求 parsel: 解析数据 jieba pandas stylecloud 第三方模块安装&#xff1a; win R 输入cmd 输入安装命令 pip install 模块名 (如果你…

Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放

技术诉求 我们在做GB28181设备对接模块和RTMP直播推送模块的时候&#xff0c;遇到这样的技术需求&#xff0c;设备&#xff08;如执法记录仪&#xff09;侧除了采集传统的摄像头外&#xff0c;还需要对接比如大疆等第三方数据源&#xff0c;确保按照GB28181规范和RTMP协议规范…