目录

一、AT24C02存储器

1、AT24C02存储器介绍

2、存储器简化模型

3、AT24C02存储器原理图

二、I²C总线

1、I²C总线的介绍

2、I²C电路

3、I²C时序图

3.1I²C开始和结束时序图

3.2I²C主机发送和接收时序图

3.3I²C主机发送应答/接收应答

4、I²C数据帧发送/接收方式

4.1主机向从机发送数据

4.2主机从从机接收数据

4.3复合格式(主机先发送数据,再接收从机数据)

4.4两种变形——字节写和随机读

5、利用独立按键写入读取数字

6、利用定时器、数码管、独立按键、AT24C02制作秒表

6.1main.c

6.2Nixie.c

6.3key.c

三、DS18B20温度传感器

1、DS18B20温度传感器介绍

2、单总线电路规范

3、单总线时序结构

3.1初始化

3.2发送一位

3.3接收一位

3.4发送/接收一个字节

4、DS18B20操作流程

5、BS18B20读取环境温度

5.1main.c

5.2OneWire.c

5.3DS18B20.c

6、DS18B20温度报警器

6.1main.c

6.2OneWire.c

6.3Key.c

6.4AT24C02.c

6.5Buzzer.c


一、AT24C02存储器

1、AT24C02存储器介绍

AT24C02是一种可以实现掉电不丢失的存储器。易失性存储器RAM存储速度快,非易失性存储器ROM存储速度慢;这俩特性类似缓存和磁盘。

存储介质:E²PROM(可擦写的只读存储器);

通讯接口:I²C总线;

容量:256字节。

2、存储器简化模型

3、AT24C02存储器原理图

二、I²C总线

1、I²C总线的介绍

I²C总线是一种通用数据总线,有两根通信线SCL(串行时钟线)、SDA(串行数据线,只有一根线,双向),是一种同步、半双工带数据应答的通信协议。

2、I²C电路

1、所有I²C设备的中SCL、SDA各自连接在一起;

2、设备的SCL和SDA均要配置成开漏输出模式;

3、SCL和SDA各添加一个上拉电阻,阻值一般KΩ级别;

开漏输出是为了单一模块间通信的过程中,让其他模块对外呈现高阻态。如果在通信的过程中,其他模块是上拉电路,虽然上拉能力弱,但是多路并联会使上拉能力增强,可能会对正在通信的模块造成影响。

上拉电阻作用:如图所示,SCL和SDA各接一个外接电阻,电路就会由开漏输出变成弱上拉模式,那么CPU想输出1,内部开关闭合,反之开关断开即可。

那么问题来了,多机通讯时,如何确定接收端是谁?多机通讯时,通过时序确定谁和谁通信。

3、I²C时序图

3.1I²C开始和结束时序图

3.2I²C主机发送和接收时序图

主机发送一个字节

主机接收一个字节

1、当SCL为高电平时,SDA的跳变表示开始和结束状态;SDA电平不变表示正在读取和发送数据。

2、主机接收从机的数据时,需要解除对SDA的控制权,即从机发送数据前将主机SDA置1。

3.3I²C主机发送应答/接收应答

1、主机接收完从机1个字节数据后,主机需要向从机发送应答。0表示应答,1表示非应答。

2、主机发送至从机1个字节数据后,从机需要向主机接收应答。0表示应答,1表示非应答。因为是从机发送,所以主机要移交SDA控制权。

4、I²C数据帧发送/接收方式

4.1主机向从机发送数据

4.2主机从从机接收数据

4.3复合格式(主机先发送数据,再接收从机数据)

本质是上面两种方式的组合。可以理解为主机向从机提问,从机回复问题。

4.4两种变形——字节写和随机读

AT24C02的固定地址为1010,可配置地址本开发板上为000,所以从机地址+W为0XA0,从机地址+R为0xA1。

5、利用独立按键写入读取数字

unsigned char KeyNum;
unsigned int Num;
void main()
{LCD_Init();LCD_ShowNum(1,1,Num,5);while(1){KeyNum=Key();if(KeyNum==1){Num++;LCD_ShowNum(1,1,Num,5);}if(KeyNum==2){Num--;LCD_ShowNum(1,1,Num,5);}if(KeyNum==3){AT24C02_WriteByte(0,Num%256);//写入低8位delay_ms(5);//每次写完延时5msAT24C02_WriteByte(1,Num/256);//写入高8位delay_ms(5);//每次写完延时5msLCD_ShowString(2,1,"Write success");delay_ms(1000);LCD_ShowString(2,1,"              ");}if(KeyNum==4){Num=AT24C02_ReadByte(0);//读出低8位Num|=AT24C02_ReadByte(1)<<8;//读出高8位LCD_ShowNum(1,1,Num,5);LCD_ShowString(2,1,"Read success");delay_ms(1000);LCD_ShowString(2,1,"              ");}}
}

6、利用定时器、数码管、独立按键、AT24C02制作秒表

6.1main.c

#include <REGX52.H>
#include "key.h"
#include "Timer0.h"
#include "Nixie.h"
#include "AT24C02.h"
#include "delay.h"
unsigned char KeyNum;
unsigned char Min,Sec,MiniSec;
unsigned char RunFlag;
void main()
{Timer0_Init();while(1){KeyNum=Key();if(KeyNum==1)//暂停{RunFlag=!RunFlag;}else if(KeyNum==2)//清零{Min=Sec=MiniSec=0;}else if(KeyNum==3)//写入AT24C02{AT24C02_WriteByte(0,Min);delay_ms(5);AT24C02_WriteByte(1,Sec);delay_ms(5);AT24C02_WriteByte(2,MiniSec);delay_ms(5);}else if(KeyNum==4)//读出AT24C02{Min=AT24C02_ReadByte(0);Sec=AT24C02_ReadByte(1);MiniSec=AT24C02_ReadByte(2);}Nixie_SetBuff(1,Min/10);Nixie_SetBuff(2,Min%10);Nixie_SetBuff(3,11);Nixie_SetBuff(4,Sec/10);Nixie_SetBuff(5,Sec%10);Nixie_SetBuff(6,11);Nixie_SetBuff(7,MiniSec/10);Nixie_SetBuff(8,MiniSec%10);}}
void Sec_Loop()
{if(RunFlag!=0){MiniSec++;if(MiniSec>=100){MiniSec=0;Sec++;if(Sec>=60){Sec=0;Min++;}}}
}
void Timer0_Routine() interrupt 1
{static unsigned int T0Count1,T0Count2,T0Count3;//函数栈帧结束后保留T0CountTH0=64535/256;//每次进中断函数后,让这两个寄存器重新回到初值TL0=64535%256;T0Count1++;//每中断一次T0Count++if(T0Count1>=(20/(12/11)))//达到了定时20毫秒的作用(晶振11.0592){T0Count1=0;//重置为0Key_Loop();}T0Count2++;if(T0Count2>=(2/(12/11)))//达到了定时2毫秒的作用(晶振11.0592){T0Count2=0;//重置为0Nixie_Loop();}T0Count3++;if(T0Count3>=(10/(12/11)))//达到了定时10毫秒的作用(晶振11.0592){T0Count3=0;//重置为0Sec_Loop();}
}

使用定时器中断控制数码管持续扫描、独立按键循环检测。(无需延时)

使用定时器中断控制秒表数字流动。

独立按键用于展示不同的效果,按键1表示秒表运行/暂停,按键2表示秒表数据清零,按键3存储秒表数据至AT24C02,秒表4读取AT24C02的数据至数码管,秒表显示存储的内容。

6.2Nixie.c

unsigned char Nixie_buff[9]={0,10,10,10,10,10,10,10,10};
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0X00,0X40};
void Nixie_SetBuff(unsigned char Location,Number)
{Nixie_buff[Location]=Number;
}
//数码管显示子函数
void Nixie_Scan(unsigned char Location,Number)
{P0=0x00;              //段码清0,消影switch(Location)        //位码输出{case 1:P2_4=1;P2_3=1;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 8:P2_4=0;P2_3=0;P2_2=0;break;}P0=NixieTable[Number]; //段码输出
}
void Nixie_Loop()
{static unsigned char i=1;//计数Nixie_Scan(i,Nixie_buff[i]);i++;if(i>=9){i=1;}
}

6.3key.c

unsigned char Key_KeyNum;
unsigned char Key()
{unsigned char Tmp=Key_KeyNum;Key_KeyNum=0;return Tmp;
}
unsigned char Key_GetStat()
{unsigned char KeyNumber=0;if(P3_1==0){KeyNumber=1;}if(P3_0==0){KeyNumber=2;}if(P3_2==0){KeyNumber=3;}if(P3_3==0){KeyNumber=4;}return KeyNumber;
}
void Key_Loop()
{static unsigned char NowState,LastState;LastState=NowState;NowState=Key_GetStat();if(LastState==1&&NowState==0)//松手状态(按键弹起){Key_KeyNum=1;}if(LastState==2&&NowState==0){Key_KeyNum=2;}if(LastState==3&&NowState==0){Key_KeyNum=3;}if(LastState==4&&NowState==0){Key_KeyNum=4;}
}

三、DS18B20温度传感器

1、DS18B20温度传感器介绍

DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点。

测温范围:-55°C 到 +125°C

通信接口:1-Wire(单总线)异步、半双工

其它特征:可形成总线结构、内置温度报警功能、可寄生供电

2、单总线电路规范

为了多机通讯,设备的DQ均要配置成开漏输出模式并且DQ需要添加一个上拉电阻,阻值一般为4.7KΩ左右

若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路

3、单总线时序结构

3.1初始化

主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线。

3.2发送一位

主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us

3.3接收一位

主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us

3.4发送/接收一个字节

发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)

接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

4、DS18B20操作流程

初始化:从机复位,主机判断从机是否响应(从机是否存在)

ROM操作:ROM指令+本指令需要的读写操作

功能操作:功能指令+本指令需要的读写操作

5、BS18B20读取环境温度

5.1main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "delay.h"
#include "DS18B20.h"
float T;
void main()
{LCD_Init();DS18B20_ConvertTemperature();//DS18B20温度转换delay_ms(1000);//延时1秒,提前读好,进while循环后读出的就是实际温度while(1){DS18B20_ConvertTemperature();//DS18B20温度转换T=DS18B20_ReadTemperature();if(T<0){LCD_ShowChar(2,1,'-');T=-T;}else{LCD_ShowChar(2,1,'+');}LCD_ShowNum(2,2,T,3);LCD_ShowChar(2,5,'.');LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);}
}

5.2OneWire.c

#include <REGX52.H>sbit OneWire_DQ=P3^7;
//初始化
unsigned char OneWire_Init()
{unsigned char i;unsigned char AckBit;OneWire_DQ=1;OneWire_DQ=0;//主机将总线拉低i = 227;while (--i);//大概延时500μs>480μsOneWire_DQ=1;//主机再拉高总线i = 29;while (--i);//大概延时70μsAckBit=OneWire_DQ;//读取从机应答i = 227;while (--i);//再延时500μs走完初始化时序return AckBit;
}//发送一位
void OneWire_SendBit(unsigned char Bit)
{unsigned char i;OneWire_DQ=0;//主机将总线拉低i = 4;while (--i);//延时10μsOneWire_DQ=Bit;//把数据给总线。发0,从机将在30μs后读到0;反之读到1i = 23;while (--i);//延时50μsOneWire_DQ=1;//主机恢复总线
}//接收一位
unsigned char OneWire_ReceiveBit()
{unsigned char Bit;unsigned char i;OneWire_DQ=0;//主机将总线拉低i = 2;while (--i);//延时5μsOneWire_DQ=1;//主机将总线释放i = 2;while (--i);//延时5μsBit=OneWire_DQ;//主机取样i = 23;while (--i);//延时50μsreturn Bit;
}//发送一个字节
void OneWire_SendByte(unsigned char Byte)
{unsigned char i=0;for(i=0;i<8;++i){OneWire_SendBit(Byte&(0X01<<i));}
}
//接收一个字节
unsigned char OneWire_ReceiveByte()
{unsigned char Byte=0X00;unsigned char i=0;for(i=0;i<8;++i){Byte|=(OneWire_ReceiveBit()<<i);}return Byte;
}

5.3DS18B20.c

#include <REGX52.H>
#include "OneWire.h"
#define DS18B20_SKIP_ROM 0XCC
#define DS18B20_CONVERT_T 0X44
#define DS18B20_READ_SCRATCHPAD 0XBE
//DS18B20温度转换
void DS18B20_ConvertTemperature()
{OneWire_Init();//初始化OneWire_SendByte(DS18B20_SKIP_ROM);//跳过ROMOneWire_SendByte(DS18B20_CONVERT_T);//温度转变
}
//温度读取
float DS18B20_ReadTemperature()
{unsigned char TLSB,TMSB;int Temp;float T;OneWire_Init();//初始化OneWire_SendByte(DS18B20_SKIP_ROM);//跳过ROMOneWire_SendByte(DS18B20_READ_SCRATCHPAD);//读出暂存器的数据TLSB=OneWire_ReceiveByte();//先读出LSBTMSB=OneWire_ReceiveByte();//再读出MSBTemp=(TMSB<<8)|TLSB;//组合成intT=Temp/16.0;//看图,最低位是2^-4而不是2^0,int要/16.0移回去return T;
}

目前室温约为17℃。

6、DS18B20温度报警器

这里有一个单总线的缺点,单总线是严格依照时序电平的持续时间来确定当前执行的是什么操作。当我们使用定时器时,就会打断这个时序。所以单总线的时序一旦开始便不能中途打断,时序开始时必须先关闭定时器。所以单总线的模块和其他需要定时器操作的外设在一起时,为了单总线设备的运行,时序开始时必须关闭定时器,可能会影响其他外设(例如秒表的准确性)。

6.1main.c

#include <REGX52.H>
#include "DS18B20.h"
#include "delay.h"
#include "AT24C02.h"
#include "LCD1602.h"
#include "key.h"
#include "Timer0.h"
#include "Buzzer.h"
float T,TShow;//表示温度
char TLow,THigh;//表示温度最高和最低值
unsigned char KeyNum;
void main()
{DS18B20_ConvertTemperature();//DS18B20温度转换delay_ms(1000);//延时1秒,提前读好,进while循环后读出的就是实际温度TLow=AT24C02_ReadByte(0);THigh=AT24C02_ReadByte(1);//将0,1地址处TLow和THigh读出来if(THigh>125||TLow<-55||THigh<=TLow)//判断AT24C02中存储的数据对不对{THigh=125;TLow=-55;}LCD_Init();LCD_ShowString(1,1,"T:");LCD_ShowString(2,1,"TH:");LCD_ShowString(2,9,"TL:");Timer0_Init();while(1){//温度读取及显示DS18B20_ConvertTemperature();//DS18B20温度转换T=TShow=DS18B20_ReadTemperature();if(T<0){LCD_ShowChar(1,3,'-');TShow=-T;}else{LCD_ShowChar(1,3,'+');}LCD_ShowNum(1,4,TShow,3);LCD_ShowChar(1,7,'.');LCD_ShowNum(1,8,(unsigned long)(TShow*10000)%10000,4);//阈值判断及显示LCD_ShowSignedNum(2,4,THigh,3);LCD_ShowSignedNum(2,12,TLow,3);KeyNum=key();if(KeyNum!=0){if(KeyNum==1){++THigh;if(THigh>125){THigh=125;}}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;}}AT24C02_WriteByte(0,TLow);delay_ms(5);AT24C02_WriteByte(1,THigh);delay_ms(5);}if(T>THigh){LCD_ShowString(1,13,"OV:H");Buzzer_Time(1000);}else if(T<TLow){LCD_ShowString(1,13,"OV:L");Buzzer_Time(1000);}else{LCD_ShowString(1,13,"    ");}}
}
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;//函数栈帧结束后保留T0CountTH0=64535/256;//每次进中断函数后,让这两个寄存器重新回到初值TL0=64535%256;T0Count++;//每中断一次T0Count++if(T0Count>=(20/(12/11)))//达到了定时20毫秒的作用(晶振11.0592){T0Count=0;//重置为0Key_Loop();}
}

6.2OneWire.c

#include <REGX52.H>sbit OneWire_DQ=P3^7;
//初始化
unsigned char OneWire_Init()
{unsigned char i;unsigned char AckBit;EA=0;//关闭定时器OneWire_DQ=1;OneWire_DQ=0;//主机将总线拉低i = 227;while (--i);//大概延时500μs>480μsOneWire_DQ=1;//主机再拉高总线i = 29;while (--i);//大概延时70μsAckBit=OneWire_DQ;//读取从机应答i = 227;while (--i);//再延时500μs走完初始化时序EA=1;//重新打开定时器return AckBit;
}//发送一位
void OneWire_SendBit(unsigned char Bit)
{unsigned char i;EA=0;OneWire_DQ=0;//主机将总线拉低i = 4;while (--i);//延时10μsOneWire_DQ=Bit;//把数据给总线。发0,从机将在30μs后读到0;反之读到1i = 23;while (--i);//延时50μsOneWire_DQ=1;//主机恢复总线EA=1;
}//接收一位
unsigned char OneWire_ReceiveBit()
{unsigned char Bit;unsigned char i;EA=0;OneWire_DQ=0;//主机将总线拉低i = 2;while (--i);//延时5μsOneWire_DQ=1;//主机将总线释放i = 2;while (--i);//延时5μsBit=OneWire_DQ;//主机取样i = 23;while (--i);//延时50μsEA=1;return Bit;
}//发送一个字节
void OneWire_SendByte(unsigned char Byte)
{unsigned char i=0;for(i=0;i<8;++i){OneWire_SendBit(Byte&(0X01<<i));}
}
//接收一个字节
unsigned char OneWire_ReceiveByte()
{unsigned char Byte=0X00;unsigned char i=0;for(i=0;i<8;++i){Byte|=(OneWire_ReceiveBit()<<i);}return Byte;
}

6.3Key.c

#include "key.h"
#include "delay.h"
#include <REGX52.H>
unsigned char Key_KeyNum;
unsigned char Key()
{unsigned char Tmp=Key_KeyNum;Key_KeyNum=0;return Tmp;
}
unsigned char Key_GetStat()
{unsigned char KeyNumber=0;if(P3_1==0){KeyNumber=1;}if(P3_0==0){KeyNumber=2;}if(P3_2==0){KeyNumber=3;}if(P3_3==0){KeyNumber=4;}return KeyNumber;
}
void Key_Loop()
{static unsigned char NowState,LastState;LastState=NowState;NowState=Key_GetStat();if(LastState==1&&NowState==0)//松手状态(按键弹起){Key_KeyNum=1;}if(LastState==2&&NowState==0){Key_KeyNum=2;}if(LastState==3&&NowState==0){Key_KeyNum=3;}if(LastState==4&&NowState==0){Key_KeyNum=4;}
}

6.4AT24C02.c

#include <REGX52.H>
#include "IIC.h"
#define AT24C02_ADDRESS 0XA0
//字节写:在写入地址中写入Data
void AT24C02_WriteByte(unsigned char WordAddress,unsigned char Data)
{IIC_Start();//开始函数IIC_SendByte(AT24C02_ADDRESS);//发送从机地址+WIIC_ReceiveAck();//接收应答IIC_SendByte(WordAddress);//发送写入地址IIC_ReceiveAck();//接收应答IIC_SendByte(Data);//发送DataIIC_ReceiveAck();//接收应答IIC_Stop();//终止函数
}
//随机读:读出WordAddress地址中的Data
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{unsigned char Data;IIC_Start();//开始函数IIC_SendByte(AT24C02_ADDRESS);//发送从机地址+WIIC_ReceiveAck();//接收应答IIC_SendByte(WordAddress);//发送写入地址IIC_ReceiveAck();//接收应答IIC_Start();//开始函数IIC_SendByte(AT24C02_ADDRESS|0X01);//发送从机地址+RIIC_ReceiveAck();//接收应答Data=IIC_ReceiveByte();//接收一个字节IIC_SendAck(0X01);//发送应答IIC_Stop();//终止函数return Data;
}

6.5Buzzer.c

#include "Buzzer.h"
#include <REGX52.H>
#include "delay.h"
#include <INTRINS.H>
sbit Buzzer=P2^5;
void Buzzer_Delay500us()        //@11.0592MHz
{unsigned char i;_nop_();i = 227;while (--i);
}//调用这个函数,蜂鸣器就响多少秒
void Buzzer_Time(unsigned int ms)
{unsigned int i;for(i=0;i<ms*2;++i){Buzzer=!Buzzer;Buzzer_Delay500us();//必须要有延时,保证高低电平维持0.5ms(几字波形)}
}

【51单片机】AT24C02存储器(I²C总线)/DS18B20温度传感器(单总线)相关推荐

  1. 51单片机之外部引脚及总线接口

    51单片机之外部引脚及总线接口 MCS-51系列外部引脚 总线结构: 冯诺依曼结构: 哈弗结构: 寻址空间的区分: MCS-51系列外部引脚 记忆方法: 1.在前面的存储器和特殊功能寄存器篇讲过,标志 ...

  2. 51单片机AT24C02写读流水灯实例+Proteus仿真

    51单片机AT24C02写读流水灯实例+Proteus仿真 Proteus仿真 这个流水灯的状态是通过读取AT24C02地址中的数值来改变的.(有点废AT24C02) 程序代码 #include &l ...

  3. (给自己看)51单片机AT24C02

    AT24C02.c文件 #include <regx52.h> #include "I2C.h"#define AT24C02_ADDRESS 0xA0 // 不需要初 ...

  4. 使用普中科技51单片机进行(I^2)C总线操作

    /*C51单片机学习打卡*/ /*观看郭天祥老师教学视频,使用普中科技51单片机开发板进行学习(I^2)C总线操作*/ /*功能:在开发版上进行999秒计时,在单片机掉电情况下可以记录最后一秒的数据* ...

  5. 基于51单片机多路温度检测proteus仿真 ds18b20

    本设计是基于51单片机多路温度检测proteus仿真_ds18b20(仿真+程序+原理图) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0042 ...

  6. 51单片机 AT24C02 PROTEUS 读写程序 源码

    #include <reg52.h> #include <intrins.h> #include <stdio.h> #include <stdlib.h&g ...

  7. 基于51单片机的数字电子钟

    目录 摘  要 1.课程设计任务 1.1课程设计题目 1.2设计的要求 2.设计总体方案 2.1初步设计方案 2.2芯片的选型 2.2.1时钟芯片的选择 2.2.2温度传感器的选择 2.2.3显示电路 ...

  8. 基于51单片机的烟雾火灾报警系统

    基于51单片机的烟雾火灾报警系统 功能 DS18B20温度传感器.MQ-2烟雾传感器 ADC0832模数转换 (1)LCD液晶显示屏实时显示当前的烟雾值和温度值: (2)温度和烟雾的报警值可以通过按键 ...

  9. 基于51单片机智能鱼缸鱼塘养殖宠物喂食系统

    功能介绍 以51单片机作为主控系统: 通过DS18B20温度传感器采集当前的温度: 可以通过继电器进行换水控制和增氧: 通过LCD1602液晶显示当前信息和参数: 通浊度传感器采集当前水族箱内水质浊度 ...

最新文章

  1. java修改jar包
  2. 用SQL语句添加删除修改字段
  3. ASP错误捕获的几种常规处理方式
  4. 2019ICPC(沈阳) - Fish eating fruit(树形dp+树根转移)
  5. 使用RichTextBox控件实现系统剪切板功能
  6. sql integer字置为空_请写一个函数来检查用户提交的数据是否为整数
  7. linux系统怎么装锐捷,Linux锐捷上网安装过程
  8. 关于virtual box安装windows xp虚拟机遇到的一个问题
  9. php 动态生成网站地图,DedeCMS网站地图动态生成方法
  10. Excel显示公式栏/编辑栏
  11. oracle 数据库回收站,Oracle数据库的回收站
  12. 计算机毕设Python+Vue医院人事及科室病区管理(程序+LW+部署)
  13. java根据前序和中序建树_(Java实现)二叉树---根据前序、中序、后序数组还原二叉树...
  14. 两个进程共享内存,一个写,一个读
  15. Socket 和 ServerSocket
  16. OV、DV、EV证书的区别
  17. js将页面转成PDF文档
  18. CAD建筑制图入门加老虎窗
  19. 抖音神曲是如何“造”出来的?
  20. Druid 的 WallFilter 抛出 sql injection violation, comment not allow 问题的解决方法

热门文章

  1. 如何确定抽样的样本数量
  2. VUE3 vue-devtools 调试工具下载安装
  3. mysql联合索引如何创建
  4. calcHist的使用
  5. 大数据面试题——数据库
  6. java计算机毕业设计Web商铺租赁管理系统MyBatis+系统+LW文档+源码+调试部署
  7. Java架构师成长之道之Java架构师技术栈
  8. JVM调优之 -Xms -Xmx -Xmn -Xss
  9. Java核心技术卷一 -第九章:集合
  10. MySQL中的uuid()和uuid_short()函数