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

news2024/12/23 4:31:10

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:对达林顿管还不是很清楚

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

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

相关文章

领域偏移:协变量移位下的域自适应

现在我们将焦点转移到一种叫做协变量转移的扰动上。我们在一个分类或回归设置中工作&#xff0c;我们希望从x预测y&#xff0c;并假设p≈(y | x)和p∗(y | x)是相同的(标记函数在训练和测试之间不会改变) 假设 (Covariate Shift)。对于列车分布p~和检验分布p∗&#xff0c;我们…

安达发|纺织行业APS系统中的物料替代解决方案

在纺织行业中&#xff0c;物料替代是应对原材料短缺、成本波动和供应链不确定性的一种重要策略。高级计划与排程系统&#xff08;APS&#xff09;通过集成物料替代功能&#xff0c;可以帮助企业在保持生产效率的同时&#xff0c;灵活应对市场变化。本文将探讨纺织行业在APS系统…

Leetcode Hot 100 | 543.二叉树的直径 | 递归+优化

写法一 自己一开始直接写的&#xff0c;没考虑时间复杂度… class Solution {/*递归思路&#xff1a;不准进递归&#xff08;除非之后用简单例子验证一下&#xff09;将方法按照自己想要返回的值来补充其他的代码细节&#xff1b;用最值来模拟返回结果补充代码细节&#xff0…

Win10鼠标总是频繁自动失去焦点-非常有效-重启之后立竿见影

针对Win10鼠标频繁自动失去焦点的问题&#xff0c;可以尝试以下解决方案&#xff1a; 一、修改注册表&#xff08;最有效的方法-重启之后立竿见影&#xff09; 打开注册表编辑器&#xff1a; 按下WindowsR组合键&#xff0c;打开运行窗口。在运行窗口中输入“regedit”&#x…

什么是reactor以及其三种版本

写在前面 本文来看下什么是reactor以及其三种版本。 1&#xff1a;什么是reactor以及其三种版本 为了更好的理解什么是reactor&#xff0c;我们结合现实生活中的例子来看下。 翠花是个貌美如花的姑娘&#xff0c;人称赛东施&#xff0c;她的梦想是嫁给王子&#xff0c;可是天…

【机器学习-无监督学习】降维与主成分分析

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…

揭秘帕金森病:多因素交织下的“沉默杀手”

在老年人群中&#xff0c;帕金森病如同一位“沉默的杀手”&#xff0c;悄然侵袭着无数人的生活。它以其独特的静止性震颤、运动迟缓、肌强直和姿势平衡障碍等症状&#xff0c;让患者的生活质量大打折扣。那么&#xff0c;帕金森病究竟是如何得的呢&#xff1f;本文将带您深入探…

基于Springboot+Vue的基于协同过滤算法的个性化音乐推荐系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…

Android 13.0 系统wifi列表显示已连接但无法访问网络问题解决

1.前言 在13.0的系统rom产品定制化开发中,在wifi模块也很重要,但是在某些情况下对于一些wifi连接成功后,确显示已连接成功,但是无法访问互联网 的情况,所以实际上这时可以正常上网的,就是显示的不正常,所以就需要分析连接流程然后解决问题 如图所示: 2.系统wifi列表显示…

【Spring Boot 入门三】Spring Boot与数据库集成 - 构建数据驱动的应用

一、引言 在之前的文章中&#xff0c;我们已经对Spring Boot有了初步的认识&#xff0c;了解了如何构建第一个Spring Boot应用&#xff0c;以及如何通过配置文件来掌控应用的设置。这些知识为我们进一步探索Spring Boot与数据库的集成奠定了坚实的基础。 数据库是现代应用的核…

QSqlDatabase在多线程中的使用

Qt中多线程使用数据库_qt数据库管理类支持多数据库,多线程-CSDN博客 1. 代码&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError>…

【原创】基于websocket的实时文本转语音功能

功能实现&#xff0c;将长文本分段实时转成音频流&#xff0c;达到边转换边播放的效果&#xff0c;减少等待效果&#xff0c;像豆包通义千问chatgpt差不多也是这样实现的&#xff0c; 下面的效果展示 20240930_084035_哔哩哔哩_bilibili【原创】基于websocket的实时文本转语音…

Java 每日一刊(第18期):集合

文章目录 前言1. Java 集合框架概述1.1 Java 集合框架的定义和意义1.2 Java 集合框架的历史演进1.3 集合框架的基本组成部分1.4 Java 集合的优势1.5 Java 集合与数组的区别与关系 2. Java 集合框架的核心接口2.1 Collection 接口2.2 List 接口2.3 Set 接口2.4 Queue 接口2.5 Ma…

无人机在科研与教育领域的应用!

一、无人机在科研领域的应用 地理测绘与遥感&#xff1a; 无人机可以搭载相机或激光雷达等传感器&#xff0c;进行高分辨率的航拍&#xff0c;用于制作数字地形模型、生态环境监测、土地利用规划等。 在地理信息获取、地质勘察等领域&#xff0c;无人机能够高效地完成测量任…

Java中正则表达式(完整详解,附有案例+代码)

文章目录 三十三.正则表达式33.1 概述33.2 Test 三十三.正则表达式 33.1 概述 字符类 [abc]a、b 或 c&#xff08;简单类&#xff09;[^abc]任何字符&#xff0c;除了 a、b 或 c&#xff08;否定&#xff09;[a-zA-Z]a 到 z 或 A 到 Z&#xff0c;两头的字母包括在内&#x…

MQTT--EMQX入门+MQTTX使用

目录 1、什么是EMQX&#xff1f;1.1 EMQX介绍1.2 EMQX特点1.3 与物联网之间的关系以及主要的产品主要的产品 2、安装启动2.1 基本命令2.2 目录结构 3、MQTTX客户端3.1 连接配置 总结PS: 1、什么是EMQX&#xff1f; 首先你得有MQTT的知识&#xff0c;不认识MQTT的小伙伴可以先看…

JMeter对jdbc request以及foreach和loop controller的使用

Jmeter中jdbc request和foreach控制器 1. 使用variable name实现对数据库查询结果的遍历 在foreach controller中&#xff0c;注意要做variable name的关联(correlation), 否则没法取回这里的jdbc request返回的结果。这里的input variable prefix一定要和jdbc request中的var…

十七、触发器

文章目录 0. 引入1. 触发器概述2. 触发器的创建2.1 触发器的创建2.2 代码举例 3. 查看、删除触发器3.1 查看触发器3.2 删除触发器 4. 触发器的优缺点4.1 优点4.2 缺点4.3 注意点 0. 引入 在实际开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;有 2 个或者多个相互关联…

《蓝桥杯算法入门》(C/C++、Java、Python三个版本)24年10月出版

推荐&#xff1a;《算法竞赛》&#xff0c;算法竞赛大全书&#xff0c;网购&#xff1a;京东 天猫  当当 文章目录 《蓝桥杯算法入门》内容简介本书读者对象作者简介联系与交流《蓝桥杯算法入门 C/C》版目录 《蓝桥杯算法入门 Java》版目录 《蓝桥杯算法入门 Python》版目录 …

vscode 连接服务器 不用输密码 免密登录

vscode 免密登录服务器 1. 本地端1&#xff09;生成密钥2&#xff09;vscode的config文件中添加id_rsa文件路径 2. 服务器端1&#xff09;在 authorized_keys 文件中加入密钥&#xff1a;2&#xff09;修改authorized_keys文件权限 1. 本地端 1&#xff09;生成密钥 在命令行…