51单片机学习第六课---B站UP主江协科技

DS18B20

1、基本知识讲解

 

2、DS18B20读取温度值

main.c

#include<regx52.h>
#include"delay.h"
#include"LCD1602.h"
#include"key.h"
#include"DS18B20.h"

float T;
void main ()
{
  LCD_Init();
  LCD_ShowString(1,1,"temp");
  
	while(1)
	{
	  DS18B20_convert();
	  T=DS18B20_read();
	  if(T<0)
	  {
	  	LCD_ShowChar(2,1,'-');	//显示负号
		T=-T;
	  }
	 else
	  {
	  	LCD_ShowChar(2,1,'+');	 //显示正号
		T=T;
	  }
	 LCD_ShowNum(2,2,T,3);	 //显示正整数  ,精度是3,-55~125
	 LCD_ShowChar(2,5,'.');		//显示小数点
	 LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示小数后面的数字,精度是4位 ,0.0623



	
	}

 }

		

onewire.c

#include<REGX52.h>
sbit onewire_DQ=P3^7;
unsigned char onewire_init()
{ 
unsigned char ackbit;
unsigned char i;
  onewire_DQ=1;
  onewire_DQ=0;
  i = 247;
  while (--i);		//延时500us
  onewire_DQ=1;
  i = 32;			//延时70us
  while (--i);
  ackbit=onewire_DQ;
  i = 247;			//延时500us,这里从机拉低60-240us会自动释放总线
  while (--i);
  return ackbit;
}
void  onewire_sendbit(unsigned char Bit)
{
   unsigned char i;
   onewire_DQ=0;
   i = 4;
   while (--i);//延时10us
   onewire_DQ=Bit;	//如果bit=0,则DQ继续拉低50us,加上前面10us,刚好满足60us.如果bit=1,则DQ相当10us后总线释放,接着继续释放50us
   	i = 24;
	while (--i);//延时50us
   onewire_DQ=1;

}
unsigned char onewire_receivebit()
{
   unsigned char i;
   unsigned char Bit;
   onewire_DQ=0;
   	i = 2;
	while (--i);//主机拉低总线5us
   onewire_DQ=1;
   	i = 2;
	while (--i);//主机释放总线5us
	Bit=onewire_DQ;//DS18B20将会发送0或1,此时主机读取数据
   	i = 24;
	while (--i);//延时50us
	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()
{
unsigned char i;
unsigned char byte=0x00;
for(i=0;i<8;i++)
{
 if(onewire_receivebit())
 {
 byte=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


void DS18B20_convert()	   
{
   onewire_init() ;	 //初始化
   onewire_sendbyte(DS18B20_SKIP_ROM); //跳过ROM
   onewire_sendbyte(DS18B20_CONVERT_T);	//温度转换
}

float DS18B20_read()		
{  
   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;					  //由于存储小数的缘故,最低位不是从2的0次方开始,而是2的-4方开始,所以读取的值要除以16
   return T;
}

3、DS18B20温度告警器

按键K1实现对温度上限值的加加,K2实现对温度上限值的减减,按键K3实现对温度下限值的加加,K4实现对温度下限值的减减,运用at24c02对温度上限值和下限值进行存储。超过上限值LCD1602显示ov:h,低于下限值LCD1602显示ov:l。

main.c

#include<regx52.h>
#include"delay.h"
#include"LCD1602.h"
#include"key.h"
#include"DS18B20.h"
#include"at24c02.h"
#include"timer0.h"
char Tlow,Thigh; //char类型表示数据位-127~128,满足DS18B20的测温范围-55~125
float  T,Tshow;
unsigned char keynum;
void main ()
{  
   DS18B20_convert();
   Delay(1000);
   Thigh=at24c02_readbyte(0); //一开始就读取AT24C02里的数据,这个时候还没有写入
   Tlow=at24c02_readbyte(1);
   if(Thigh>125||Tlow<-55||Thigh<=Tlow){ Thigh=25;Tlow=5;}	//读出的数据可能会超出范围,所以当超出范围时,赋初值
   LCD_Init();
   Timer0_Init();
   LCD_ShowString(1,1,"T:");
   LCD_ShowString(2,1,"TH:");
   LCD_ShowString(2,9,"TL:");
   LCD_ShowSignedNum(2,4,Thigh,3);
   LCD_ShowSignedNum(2,12,Tlow,3);
	while(1)
	{
	 keynum=key();
	 DS18B20_convert();
	 T=DS18B20_read();
	 if(T<0) {LCD_ShowChar(1,3,'-');Tshow=-T;}//为什么要定一个Tshow,主要是当T为负数时,要转为正数,这样Tshow就始终是正数
	 if(T>0) {LCD_ShowChar(1,3,'+');Tshow=T;} //因为shownum只能显示正整数,而且要显示小数部分,转成正整数方便转换
	 LCD_ShowNum(1,4,Tshow,3);
	 LCD_ShowChar(1,7,'.');	 
	 LCD_ShowNum(1,8,(unsigned long)(Tshow*100)%100,2);
	 if(keynum)
	 {
	 if(keynum==1)
	 {Thigh++;
	  if(Thigh>125){Thigh=125;}	  //温度上限值不能超过DS18B20的上限
	 }
	 if(keynum==2){
	 Thigh--;
	 if(Thigh<=Tlow)	//温度上限值减减不能减到小于温度下限值
	 {
	  Thigh++;}
	 }
	 if(keynum==3){
	 Tlow++;
	 if(Tlow>=Thigh)  //温度下限值加加不能加到大于温度上限值
	 {
	  	 Tlow--;
	 }
	 }
	 if(keynum==4)
	 {
	 Tlow--;
	  if(Tlow<-55){Tlow=-55;}	   //温度下限值不能超过DS18B20的下限
	 }
	 at24c02_writebyte(0,Thigh);   //记住写入后要延时5ms
	 Delay(5);
	 at24c02_writebyte(1,Tlow);
	 Delay(5);
     LCD_ShowSignedNum(2,4,Thigh,3);
     LCD_ShowSignedNum(2,12,Tlow,3);
}
	 if(T>Thigh){
	 LCD_ShowString(1,13,"ov:H");}	//实际温度超过设定上限值告警
	 else if(T<Tlow){
	 LCD_ShowString(1,13,"ov:L");}	  //实际温度低于设定下限值告警
	 else{LCD_ShowString(1,13,"    ");}
	 }
	}
 void Timer0_Routine()        interrupt 1
{
	static unsigned  int count;	
   	TL0 = 0x18;				
	TH0 = 0xFC;
	count++;
if(count>=20)	
{
  count=0;
  key_loop();

}



}

		

onewire.c

这里增加一步关闭中断,再打开中断

#include <REGX52.H>
sbit onewire_DQ=P3^7;
unsigned char onewire_init()
{ 
unsigned char ackbit;
unsigned char i;
  onewire_DQ=1;
  onewire_DQ=0;
  EA=0;//单总线计时时不能进入中断,因为延时是us级别,中断之后再返回会计时不准,所以这里要关掉总中断,计时完后再打开。
  i = 247;
  while (--i);		//延时500us
  onewire_DQ=1;
  i = 32;			//延时70us
  while (--i);
  ackbit=onewire_DQ;
  i = 247;			//延时500us,这里从机拉低60-240us会自动释放总线
  while (--i);
  EA=1;
  return ackbit;
}
void  onewire_sendbit(unsigned char Bit)
{
   unsigned char i;
   onewire_DQ=0;
  EA=0;
   i = 4;
   while (--i);//延时10us
   onewire_DQ=Bit;	//如果bit=0,则DQ继续拉低50us,加上前面10us,刚好满足60us.如果bit=1,则DQ相当10us后总线释放,接着继续释放50us
   	i = 24;
	while (--i);//延时50us
	  EA=1;

   onewire_DQ=1;

}
unsigned char onewire_receivebit()
{
   unsigned char i;
   unsigned char Bit;
   onewire_DQ=0;
    EA=0;
   	i = 2;
	while (--i);//主机拉低总线5us
   onewire_DQ=1;
   	i = 2;
	while (--i);//主机释放总线5us
	Bit=onewire_DQ;//DS18B20将会发送0或1,此时主机读取数据
   	i = 24;
	while (--i);//延时50us
	 EA=1;
	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()
{
unsigned char i;
unsigned char byte=0x00;
for(i=0;i<8;i++)
{
 if(onewire_receivebit())
 {
 byte=byte|(0x01<<i);	   //取整体用或
 }
}
return byte;
}





LCD1602

1、基本知识讲解

2、字符、字符串 

2、LCD1602.c代码

#include<regx52.h>
sbit lcd_RS=P2^6;
sbit lcd_RW=P2^5;
sbit lcd_EN=P2^7;
#define port  P0
void LCD_Delay()	//@12.000MHz  1ms  //延时函数
{
	unsigned char data i, j;

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

void lcd_write_command(unsigned char command)	//写命令
{
   lcd_RS=0;
   lcd_RW=0;
   port=command;
   lcd_EN=1;
   LCD_Delay();//因为这里E脉冲宽度时间是us级别,而单片机执行一次命令是us级别,所以这里检测不到,所以加延时函数
   lcd_EN=0;
   LCD_Delay();

}
void lcd_write_Data(unsigned char Data)	 //写数据
{
   lcd_RS=1;
   lcd_RW=0;
   port=Data;
   lcd_EN=1;
   LCD_Delay();//因为这里E脉冲宽度时间是us级别,而单片机执行一次命令是us级别,所以这里检测不到,所以加延时函数
   lcd_EN=0;
   LCD_Delay();

}

void lcd_init()		  //初始化
{
 lcd_write_command(0x38);
 lcd_write_command(0x0C);
 lcd_write_command(0x06);
 lcd_write_command(0x01);
}

void LCD_setcursor(unsigned char line,unsigned char column)	  //定义光标位置,在第几行第几列
{
 if(line==1)
 {
  lcd_write_command(0x80|column-1);
 }
 else
 {
  lcd_write_command(0x80|(column-1)+0x40);
 }
}


void LCD_ShowChar(unsigned char line,unsigned char column,unsigned char Char) //显示一个字符
{
 LCD_setcursor(line,column);
 lcd_write_Data(Char);
}
void LCD_ShowString(unsigned char line,unsigned char column,unsigned char *String)	//显示字符串
{
 unsigned char i;
 LCD_setcursor(line,column);
 for(i=0;String[i]!='\0';i++)
{
lcd_write_Data(String[i]);
}
 
}
unsigned int pow(x,y)	   //定义一个幂函数	 例如x=6,y=4,则result=1*6*6*6*6=6^4
{
  unsigned char result=1;
  unsigned int i;
  for(i=0;i<y;i++)
  {
  	result*=x;
  }
  return result;
}
void LCD_ShowNum(unsigned char line,unsigned char column,unsigned int num,unsigned char length)	//显示十进制数字
{
	unsigned char i;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num/(pow(10,i-1))%10);

	
	}
	}
void LCD_ShowsignNum(unsigned char line,unsigned char column, int num,unsigned char length)//显示有符号十进制数字
{
	unsigned char i;
    unsigned int num1;
    LCD_setcursor(line,column);

 if(num>=0)
 {
  lcd_write_Data('+');
  num1=num;
 }
 else
 {
  lcd_write_Data('-');
  num1=-num;//有符号int的负数最小值为-32768,正数最大值为32767,取反会超出范围,所以定义一个无符号int   num1
 }

 	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num1/(pow(10,i-1))%10);
}
}
void LCD_ShowHexNum(unsigned char line,unsigned char column, unsigned int num,unsigned char length)	 //显示十六进制数
{
	unsigned char i;
	unsigned char SingleNum;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	SingleNum=num/(pow(16,i-1))%16;
	if(SingleNum<10)
	 {lcd_write_Data(0x30+SingleNum); }
	else
	{
	 {lcd_write_Data(0x41+SingleNum-10); }
	}
	
	}
	}
void LCD_ShowBinNum(unsigned char line,unsigned char column, unsigned int num,unsigned char length)	//显示二进制数
{
	unsigned char i;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num/(pow(2,i-1))%2);

	
	}


}



 main.c

#include<regx52.h>
#include"LCD1602.h"
#include"delay.h"
void main ()
{
   lcd_init();
   LCD_ShowChar(2,4,'A');
//   LCD_ShowString(1,3,"hello");
   LCD_ShowNum(2,6,66,2);
   LCD_ShowsignNum(2,10,-77,2);
//   LCD_ShowHexNum(1,8,0x55,2);
   LCD_ShowBinNum(1,1, 0x55,8);
   LCD_ShowString(1,16,"welcome to my home!");
while(1)
{
 lcd_write_command(0x1c);	//流动字幕,移屏
 Delay(500);		
}
		
}

直流电机

1、基本知识讲解

 

2、LED呼吸灯

main.c

#include<regx52.h>

sbit LED=P2^0;

void Delay(unsigned int ms)
{
 while(ms--);

}
void main ()
{



while(1)
{
unsigned char i,t;
for(i=100;i>0;i--)
   {
   for(t=0;t<20;t++)
		{	
		    LED=0;
			Delay(i);
			LED=1;
			Delay(100-i);
		}
	}
for(i=0;i<100;i++)
   {
   for(t=0;t<20;t++)
		{	
		    LED=0;
			Delay(i);
			LED=1;
			Delay(100-i);
		}
	}
  
}
}

 3、直流电机调速

按K1键实现电机的调速,并在数码管上显示档数。

main.c

#include<regx52.h>
#include"key.h"
#include"nixie.h"
#include"Timer0.h"
sbit motor=P1^0;
unsigned char counter,compare,keynum,speed;


void main ()
{
 Timer0_Init();


while(1)
		{
		  keynum=key();
		  if(keynum==1)
		  {
			speed++;speed%=4;
		  if(speed==0){ compare=0;}
		  if(speed==1){ compare=5;}
		  if(speed==2){ compare=50;}
		  if(speed==3){ compare=100;}
		  }
		  nixie (0,speed);

		}
}
 void Timer0_Routine()        interrupt 1
{
   	TL0 = 0x9C;				
	TH0 = 0xFF;
	counter++;
	counter%=100;
	if(counter<compare)
	{
	 motor=1;
	}
	else
	{
	 motor=0;
	}


}

ps:对达林顿管还不是很清楚

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt之TCP收发图片的例子

一.效果 二.实现 1.发图片 void MainWindow::slotSendImage() {matrix.rotate(90);QPixmap tempPixmap = pixmap.transformed(matrix);QBuffer buffer;tempPixmap.save(&buffer,"jpg");ui->labelImage->setPixmap(tempPixmap);int dataLength = buffer.d…

软考鸭微信小程序:助力软考备考的便捷工具

一、软考鸭微信小程序的功能 “软考鸭”微信小程序是一款针对软考考生的备考辅助工具&#xff0c;提供了丰富的备考资源和功能&#xff0c;帮助考生提高备考效率&#xff0c;顺利通过考试。其主要功能包括&#xff1a; 历年试题库&#xff1a;小程序内集成了历年软考试题&…

HarmonyOs 查看官方文档使用弹窗

1. 学会查看官方文档 HarmonyOS跟上网上的视频学习一段时间后&#xff0c;基本也就入门了&#xff0c;但是有一些操作网上没有找到合适教学的视频&#xff0c;这时&#xff0c;大家就需要养成参考官方文档的习惯了&#xff0c;因为官方的开发文档是我们学习深度任何一门语言或…

004集—— txt格式坐标写入cad(CAD—C#二次开发入门)

如图所示原始坐标格式&#xff0c;xy按空格分开&#xff0c;将坐标按顺序在cad中画成多段线&#xff1a; 坐标xy分开并按行重新输入txt&#xff0c;效果如下&#xff1a; 代码如下 &#xff1a; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; us…

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…

Pikachu-File Inclusion-远程文件包含

远程文件包含漏洞 是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的&#xff0c;因此漏洞一旦存在&#xff0c;危害性会很大。但远程文件包含漏洞的利用条件较为苛刻&#xff1b;因此&#xff0c;在web应用系统的功能设计上尽量不要让前端用户直接传变…

水下声呐数据集,带标注

水下声呐数据集&#xff0c;带标注 水下声呐数据集 数据集名称 水下声呐数据集 (Underwater Sonar Dataset) 数据集概述 本数据集是一个专门用于训练和评估水下目标检测与分类模型的数据集。数据集包含大量的水下声呐图像&#xff0c;每张图像都经过专业标注&#xff0c;标明…

银河麒麟桌面操作系统修改默认Shell为Bash

银河麒麟桌面操作系统修改默认Shell为Bash &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 在银河麒麟桌面操作系统&#xff08;ARM版&#xff09;中&#xff0c;若要将默认Shell从Dash改为Bash&#xff0c;可执行以下步骤&#xff1a; 打开…

记一次炉石传说记牌器 Crash 排查经历

大家好这里是 Geek技术前线。最近在打炉石过程中遇到了HSTracker记牌器的一个闪退问题&#xff0c;尝试性排查了下原因。这里简单记录一下 最近炉石国服回归&#xff1b;由于设备限制&#xff0c;我基本只会在 Mac 上打炉石。并且由于主要打竞技场&#xff0c;所以记牌器是必不…

河南移动:核心营业系统稳定运行超300天,数据库分布式升级实践|OceanBase案例

河南移动&#xff0c;作为电信全业务运营企业&#xff0c;不仅拥有庞大的客户群体和业务规模&#xff0c;还引领着业务产品与服务体系的创新发展。河南移动的原有核心营业系统承载着超过6000万的庞大用户量&#xff0c;管理着超过80TB的海量数据&#xff0c;因此也面临着数据规…

AI类课程的笔记

信息论、导论、模式识别&#xff08;数据挖掘&#xff09;、语义网络与知识图谱、深度学习、强化学习 &#xff08;零&#xff09;信息论 详见另一篇博文 信息论自总结笔记(仍然在更新)_信息论也更新了-CSDN博客https://blog.csdn.net/sinat_27382047/article/details/12690…

Elasticsearch 实战应用

Elasticsearch 实战应用 引言 Elasticsearch 是一个分布式、RESTful 风格的搜索和分析引擎&#xff0c;能够快速、实时地处理大规模数据&#xff0c;广泛应用于全文搜索、日志分析、推荐系统等领域。在这篇博客中&#xff0c;我们将从 Elasticsearch 的基本概念入手&#xff…

无神论文解读之ControlNet:Adding Conditional Control to Text-to-Image Diffusion Models

一、什么是ControlNet ControlNet是一种能够控制模型生成内容的方法&#xff0c;能够对文生图等模型添加限制信息&#xff08;边缘、深度图、法向量图、姿势点图等&#xff09;&#xff0c;在当今生成比较火的时代很流行。 这种方法使得能够直接提供空间信息控制图片以更细粒…

Hive数仓操作(十七)

一、Hive的存储 一、Hive 四种存储格式 在 Hive 中&#xff0c;支持四种主要的数据存储格式&#xff0c;每种格式有其特点和适用场景&#xff0c;不过一般只会使用Text 和 ORC &#xff1a; 1. Text 说明&#xff1a;Hive 的默认存储格式。存储方式&#xff1a;行存储。优点…

设计模式、系统设计 record part03

创建者模式 1.创建、使用&#xff0c;二者分离 2.降低&#xff0c;耦合度 3.使用者&#xff0c;不用关注&#xff0c;对象的创建细节 工厂模式&#xff1a; 1.对象由工厂生产&#xff0c; 2.使用者与工厂交流&#xff0c;不与对象直接打交道&#xff0c; 3.在工厂里直接更换对象…

快手:数据库升级实践,实现PB级数据的高效管理|OceanBase案例

本文作者&#xff1a;胡玉龙&#xff0c;快手技术专家 快手在较初期采用了OceanBase 3.1版本成功替换了多个核心业务、数百套的MySQL集群。至2023年&#xff0c;快手的数据量已突破800TB大关&#xff0c;其中最大集群的数据量更是达到了数百TB级别。为此&#xff0c;快手将数据…

静止坐标系和旋转坐标系变换的线性化,锁相环线性化通用推导

将笛卡尔坐标系的电压 [ U x , U y ] [U_x, U_y] [Ux​,Uy​] 通过旋转变换(由锁相环角度 θ P L L \theta_{PLL} θPLL​ 控制)转换为 dq 坐标系下的电压 [ U d , U q ] [U_d, U_q] [Ud​,Uq​]。这个公式是非线性的,因为它涉及到正弦和余弦函数。 图片中的推导过程主要…

[C++]使用C++部署yolov11目标检测的tensorrt模型支持图片视频推理windows测试通过

官方框架&#xff1a; https://github.com/ultralytics/ultralytics yolov8官方最近推出yolov11框架&#xff0c;标志着目标检测又多了一个检测利器&#xff0c;于是尝试在windows下部署yolov11的tensorrt模型&#xff0c;并最终成功。 重要说明&#xff1a;安装环境视为最基…

总结TypeScript相关知识

目录 引入认识特点安装使用变量声明类型推导 JS 和 TS 共有类型number类型boolean类型string类型Array类型null和undefined类型object类型symbol类型对象类型函数类型 可选和只读type 和 interface索引签名类型断言非空类型断言类型缩小严格赋值检测现象TS 新增类型字面量类型a…

Golang | Leetcode Golang题解之第452题用最少数量的箭引爆气球

题目&#xff1a; 题解&#xff1a; func findMinArrowShots(points [][]int) int {if len(points) 0 {return 0}sort.Slice(points, func(i, j int) bool { return points[i][1] < points[j][1] })maxRight : points[0][1]ans : 1for _, p : range points {if p[0] > …