51单片机-DS18B20(温度传感器)AT24C02(存储芯片) IIC通信-实验2-温度实时监测(可设置阈值)
作者:王开心
座右铭:刻苦专研,百折不挠,千磨万击还坚韧,任尔东西南北风!干就完了!(可交流技术)
主要利用DS18B20芯片去采集温度,通过采集的温度能够自动保存上一次温度值,在设置几个按键对温度阈值进行设置,最后可以检测温度变化,可通过蜂鸣器产生报警提示,温度显示可以在LCD1602中显示。
实验现象:
51单片,自动报警器
代码整合可参考(主页代码标题章节)(.h文件自己加)(工程文件最后免费共享)
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "AT24C02.h"
#include "IIC.h"
#include "Key.h"
#include "Buzzer.h"
#include "Timer0.h"/*
本程序需要注意,当定时器不断的去扫描按键的时候,会打断我们的延时函数,这就是为什么程序在定时器内尽量少使用延时函数
*/float T, TShow;
char TL,TH; //阈值高和低
unsigned KeyNum;
unsigned char KeyNm,TimeSetFlashFlag;void main(void)
{DS18B20_ConvertTemperature();Delay_Any(1000); TH = AT24C02_ReadByte(0); TL = AT24C02_ReadByte(1);if(TH>125 || TL<-55 ||TH<=TL){TH = 20;TL = 15;}LCD_Init(); //LCD1602初始化Timer0_Init(); //定时器扫描按键LCD_ShowString(1,1,"T:");LCD_ShowString(2,1,"TH:");LCD_ShowString(2,9,"TL:");while(1){//温度读取及显示DS18B20_ConvertTemperature();T = DS18B20_ReadTemperature();if(T<0){LCD_ShowChar(1,3,'-');//温度正负号TShow = -T;}elseLCD_ShowChar(1,3,'+');TShow = T;LCD_ShowNum(1,4,T,3); //显示温度整数部分LCD_ShowChar(1,7,'.'); //显示小数点LCD_ShowNum(1,8,(unsigned long)(T*100)%100,2); //显示小数部分,保留两位小数,最后,一定要类型转化//阈值判断及显示KeyNum = Key(); //按键设置阈值if(KeyNum){if(KeyNum == 1){TH++;Buzzer_Key();if(TH>125){TH = 125;}}if(KeyNum == 2){TH--;if(TH <= TL){TH++;}Buzzer_Key();}if(KeyNum == 3){TL++;if(TL >= TH){TL--;}Buzzer_Key();}if(KeyNum == 4){TL--;if(TL<-55){TL = -55;}Buzzer_Key();}}if(T > TH){LCD_ShowString(1,12,"T:H!!");if(TimeSetFlashFlag == 1)LCD_ShowString(1,12,"T: ");Buzzer_Siren();}else if(T < TL){LCD_ShowString(1,12,"T:L!!");if(TimeSetFlashFlag == 1)LCD_ShowString(1,12,"T: ");Buzzer_Siren();}else{LCD_ShowString(1,12,"T: NC ");}LCD_ShowSignedNum(2,4,TH,3);LCD_ShowSignedNum(2,12,TL,3);//将数据存储在存储芯片中AT24C02 ,0-255个地址AT24C02_WriteByte(0,TH); //Delay_Any(5); //写入数据必须延时5毫秒AT24C02_WriteByte(1,TL);Delay_Any(5); //写入数据必须延时5毫秒}
}//定时器中断函数void Timer0_Rountine(void) interrupt 1
{static unsigned int T0Count ,T0Count1; //Timer0_Rountine(void) 函数结束之后T0Count保留其原来的值TL0 = 0x66; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count >= 5){TimeSetFlashFlag = !TimeSetFlashFlag;T0Count = 0;Key_Loop(); //每隔20毫秒,定时器扫描一下} T0Count1++;if(T0Count1 >= 1000){ T0Count1 = 0;TimeSetFlashFlag = !TimeSetFlashFlag; } }
DS18B20.c
#include <REGX52.H>
#include "OneWire.h"//DS18B20 程序使用的寄存器进行红宏定义
#define SKIP_ROM 0XCC //ROM指令 跳过ROM ,相当于直接访问DS18B20
#define CONVERT_T 0X44 //功能指令 温度转换
#define READ_SCRATCHPAD 0XBE //功能指令 暂存器//温度转换函数 :初始化→跳过ROM →开始温度变换void DS18B20_ConvertTemperature(void)
{OneWire_Init();OneWire_SendByte(SKIP_ROM); //跳过ROM,写入一个字节数据,说我要读取温度OneWire_SendByte(CONVERT_T); //发送一个字节,让DS18B20开始温度转化}//温度读取:初始化→跳过ROM →读暂存器→连续的读操作
float DS18B20_ReadTemperature(void)
{unsigned char TLSB, TMSB;int Temp;float T;OneWire_Init();//初始化OneWire_SendByte(SKIP_ROM);OneWire_SendByte(READ_SCRATCHPAD); //跳过ROM,写入一个字节数据,说我要读取温度TLSB = OneWire_ReceiveByte();TMSB = OneWire_ReceiveByte();Temp = (TMSB<<8) | TLSB;T = Temp/16.0;return T;}
Delay.c
#include <REGX52.H>
#include "intrins.h"void Delay1ms() //@11.0592MHz
{unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);
}void Delay70us() //@11.0592MHz
{unsigned char i;_nop_();i = 29;while (--i);
}void Delay_Any(unsigned int xms) //@11.0592MHz
{unsigned char i, j;while(xms--){_nop_();i = 2;j = 199;do{while (--j);} while (--i);}
}void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void Delay50us() //@11.0592MHz
{unsigned char i;_nop_();i = 20;while (--i);
}void Delay5us() //@11.0592MHz
{
}
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');}
}
OneWire.c
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"sbit OneWire_DQ = P3^7; //单总线的管脚定义//编写5个函数 初始化、写一位、读一位、写一个字节、读一个字节//初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线unsigned char OneWire_Init(void)
{unsigned char AckBit,i;EA = 0 ; //定时器关闭(因为这个函数里面有延时函数,会和定时器扫描按键时产生冲突) 延时过程中防止被中断打断OneWire_DQ = 1; //保证拉低之前是高电平OneWire_DQ = 0; //拉低Delay1ms();//延时1ms ,至少480usOneWire_DQ = 1; //释放Delay70us();AckBit = OneWire_DQ; //应答位:存在的从机会拉低总线60~240us以响应主机Delay1ms();//延时1ms ,至少480usEA = 1 ; //定时器打开return AckBit;}//写一位数据,即主机51发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,
//然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60usvoid OneWire_SendBit(unsigned char Bit)
{//EA = 0 ; //定时器关闭(因为这个函数里面有延时函数,会和定时器扫描按键时产生冲突) 延时过程中防止被中断打断OneWire_DQ = 0; //拉低Delay10us();OneWire_DQ = Bit; //10us 将数据放到总线上,主机写,Delay50us();OneWire_DQ = 1; //释放//EA = 1 ; //定时器打开
}//接收一位:即主机51读取一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),
//读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
unsigned char OneWire_ReadBit(void)
{unsigned char Bit;EA = 0 ; //定时器关闭(因为这个函数里面有延时函数,会和定时器扫描按键时产生冲突) 延时过程中防止被中断打断OneWire_DQ = 0; //拉低Delay5us();OneWire_DQ = 1; //释放Delay5us();Bit = OneWire_DQ; //数据放到总线上,主机读Delay50us();return Bit;EA = 1 ; //定时器打开}//发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)
void OneWire_SendByte(unsigned char Byte)
{unsigned char i;EA = 0 ; //定时器关闭(因为这个函数里面有延时函数,会和定时器扫描按键时产生冲突) 延时过程中防止被中断打断for(i=0; i<8; i++){OneWire_SendBit(Byte & (0X01 << i));}EA = 1 ; //定时器打开
}//接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)unsigned char OneWire_ReceiveByte(void)
{//中断先执行变量赋初值操作,再关闭定时器中断unsigned char i, Byte = 0X00;EA = 0 ; //定时器关闭(因为这个函数里面有延时函数,会和定时器扫描按键时产生冲突) 延时过程中防止被中断打断for(i=0; i<8; i++){if(OneWire_ReadBit()){Byte |= (0x01<<i);}}return Byte;EA = 1 ; //定时器打开
}//#include <REGX52.H>引脚定义
//sbit OneWire_DQ=P3^7;///**
// * @brief 单总线初始化
// * @param 无
// * @retval 从机响应位,0为响应,1为未响应
// */
//unsigned char OneWire_Init(void)
//{
// unsigned char i;
// unsigned char AckBit;
// OneWire_DQ=1;
// OneWire_DQ=0;
// i = 247;while (--i); //Delay 500us
// OneWire_DQ=1;
// i = 32;while (--i); //Delay 70us
// AckBit=OneWire_DQ;
// i = 247;while (--i); //Delay 500us
// return AckBit;
//}///**
// * @brief 单总线发送一位
// * @param Bit 要发送的位
// * @retval 无
// */
//void OneWire_SendBit(unsigned char Bit)
//{
// unsigned char i;
// OneWire_DQ=0;
// i = 4;while (--i); //Delay 10us
// OneWire_DQ=Bit;
// i = 24;while (--i); //Delay 50us
// OneWire_DQ=1;
//}///**
// * @brief 单总线接收一位
// * @param 无
// * @retval 读取的位
// */
//unsigned char OneWire_ReceiveBit(void)
//{
// unsigned char i;
// unsigned char Bit;
// OneWire_DQ=0;
// i = 2;while (--i); //Delay 5us
// OneWire_DQ=1;
// i = 2;while (--i); //Delay 5us
// Bit=OneWire_DQ;
// i = 24;while (--i); //Delay 50us
// return Bit;
//}///**
// * @brief 单总线发送一个字节
// * @param Byte 要发送的字节
// * @retval 无
// */
//void OneWire_SendByte(unsigned char Byte)
//{
// unsigned char i;
// for(i=0;i<8;i++)
// {
// OneWire_SendBit(Byte&(0x01<<i));
// }
//}///**
// * @brief 单总线接收一个字节
// * @param 无
// * @retval 接收的一个字节
// */
//unsigned char OneWire_ReceiveByte(void)
//{
// unsigned char i;
// unsigned char Byte=0x00;
// for(i=0;i<8;i++)
// {
// if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
// }
// return Byte;
//}
AT24C02.c
#include <REGX52.H>
#include "IIC.h"#define AT24C02_ADDRESS 0XA0 //1010 0000 前四位AT24C02地址不变,最后一位决定是写还是读 1:读,即接收 0:写,即发送//仿照帧格式去写(可参考上一节IIC时序介绍)
//字节写:在WORD ADDRESS处写入数据DATA
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{IIC_Start(); //起始信号IIC_SendByte(AT24C02_ADDRESS); //发送从机地址和写操作IIC_ReceiveAck(); //接收应答位IIC_SendByte(WordAddress); //字地址:指定在WORD ADDRESS处写入数据DATAIIC_ReceiveAck(); //接收应答位IIC_SendByte(Data); //写入数据到WordAddress中IIC_ReceiveAck(); //接收应答位IIC_Stop();//结束信号}//Ack : 0:表示应答 1:表示非应答
//随机读:读出在WORD ADDRESS处的数据DATA
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{unsigned char Data;//写操作,就是先找到要通信的从机IIC_Start(); //起始信号IIC_SendByte(AT24C02_ADDRESS); //发送从机地址和写操作IIC_ReceiveAck(); //接收应答位IIC_SendByte(WordAddress); //字地址:指定在WORD ADDRESS处写入数据DATAIIC_ReceiveAck(); //接收应答位//找到对应的从机之后,开始接收从机发过来的数据IIC_Start(); //起始信号IIC_SendByte(AT24C02_ADDRESS | 0X01); //发送从机地址和读操作IIC_ReceiveAck(); //接收应答位Data = IIC_ReceiveByte(); //接收一个字节的数据IIC_SendAck(1); IIC_Stop();//结束信号return Data;
}
IIC.c
#include <REGX52.H>//位声明 ,两根线定义在单片机的管脚,也就是说SCL接在P2^1管脚,SDA接在P2^0管脚,
sbit IIC_SCL = P2^1;
sbit IIC_SDA = P2^0;//IIC的6个基本函数(符合IIC时序的基本操作,软件模拟IIC,让AT24C02继承于IIC,后期直接调用即可,无需关注底层细节,其实这个就是IIC的驱动)//起始函数
void IIC_Start(void)
{//起始条件:SCL高电平期间,SDA从高电平切换到低电平IIC_SDA = 1; //先保证SDA处于高电平状态 IIC_SCL = 1; IIC_SDA = 0;IIC_SCL = 0; }//终止函数
void IIC_Stop(void)
{//终止条件:SCL高电平期间,SDA从低电平切换到高电平IIC_SDA = 0; //先保证SDA处于低电平状态IIC_SCL = 1; IIC_SDA = 1;IIC_SCL = 0;
}//发送一个字节,发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),
//然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节(可参考上一节内容)void IIC_SendByte(unsigned char Byte)
{unsigned char i;for(i=0; i<8; i++){IIC_SDA = Byte & (0X80>>i) ;//将数据位依次放到SDA线上(高位在前)&按位与IIC_SCL = 1;IIC_SCL = 0;}}//接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),
//然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,
//即可接收一个字节(主机在接收之前,需要释放SDA)//接收一个字节数据
unsigned char IIC_ReceiveByte(void)
{unsigned char i, Byte = 0X00; //用于保存接收的字节IIC_SDA = 1; //主机在接收之前,需要释放SDA,终止对SDA的控制for(i=0; i<8; i++){IIC_SCL = 1; //拉高SCL,主机将在SCL高电平期间读取数据位if(IIC_SDA){Byte |= (0X80>>i);}IIC_SCL = 0; //SCL低电平期间,从机将数据位依次放到SDA线上(高位在前)}return Byte;
}//发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答 (IIC时序手册)
void IIC_SendAck(unsigned char AckBit)
{IIC_SDA = AckBit; //应答位,SCL低电平期间,从机将数据位依次放到SDA线上(高位在前)IIC_SCL = 1; //SCL从高到底,把数据放到SDA上IIC_SCL = 0;}//接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,
//数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)unsigned char IIC_ReceiveAck(void)
{unsigned char AckBit;IIC_SDA = 1; //主机在接收之前,需要释放SDAIIC_SCL = 1; //高电平期间,主机可以读取IIC上的数据位AckBit = IIC_SDA;IIC_SCL = 0;return AckBit;
}
Buzzer.c
#include "Buzzer.h"
#include "intrins.h"
#include <REGX52.H>sbit Buzzer = P2^5; //蜂鸣器位声明/*** @brief 蜂鸣器私有延时函数 延时500us* @param 无* @retval 无*/void Buzzer_Delay500us() //@11.0592MHz
{unsigned char i;_nop_();i = 227;while (--i);
}void Buzzer_Key()
{Buzzer = !Buzzer;Buzzer_Delay500us();}void Buzzer_Siren()//报警
{unsigned char i;while(i--){Buzzer = !Buzzer;Buzzer_Delay500us();}}
Key.c
#include <REGX52.H>
#include "Delay.h"//定时器扫描按键
unsigned char Key_KeyNumber;unsigned char Key(void)
{unsigned Temp = 0;Temp = Key_KeyNumber;Key_KeyNumber = 0;return Temp;}unsigned char Key_GetState()
{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(void)
{static unsigned char NowState,lastState; lastState = NowState;NowState = Key_GetState();if(lastState==1 && NowState==0){Key_KeyNumber = 1;}if(lastState==2 && NowState==0){Key_KeyNumber = 2;}if(lastState==3 && NowState==0){Key_KeyNumber = 3;}if(lastState==4 && NowState==0){Key_KeyNumber = 4;}}
Timer0.c
#include <REGX52.H>//由软件配置的定时器STC-ISP/**
* @brief 定时器初始化(51单片机软件内置配置的定时器)* @param 无* @retval 无*/void Timer0_Init() //1毫秒@11.0592MHz
{TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式TL0 = 0x66; //设置定时初值TH0 = 0xFC; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时//打开定时器中断ET0 = 1; EA = 1;PT0 = 0;
}//void Timer0_Init()
//{
// /*
// 采用与或式赋值法,可以把不可寻址的位进行寻址,改变其中几位而不影响其他位
// TMOD = TMOD & 0XF0; //低四位清零,高四位置一
// TMOD = TMOD | 0X01;//把TMOD的最低位置1,高四位保持不变
// 如上,改变低四位而不改变高四位
//
// */
// //TMOD = 0x01; //工作模式寄存器
// TMOD = TMOD & 0XF0; //低四位清零,高四位置一
// TMOD = TMOD | 0X01;//把TMOD的最低位置1,高四位保持不变
// //控制寄存器
// TF0 = 0;
// TR0 = 1;
//
// /*定时器赋初值 定时1ms,12Mhz的晶振,1us产生一个计数脉冲,
// 而16位的计数器是0~65535个可能,也就是65536us,65536个脉冲
// 如何差生一微秒(1ms=1000us)那么从64535开始记到65535产生一个中断
// 通过配置TL0和TH0控制处置也就是把64535变成16进制TL0是低八位两个十六进制,TH0是高八位的两十六进制*/
//
// TL0 = 64535%56;
// TH0 = 64535/256;
//
// ET0 = 1;
// EA = 1;
// PT0 = 0;
//
//}/*定时器中断函数模板
void Timer0_Rountine(void) interrupt 1
{static unsigned int T0Count ; //Timer0_Rountine(void) 函数结束之后T0Count保留其原来的值TL0 = 0x66; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count >= 1000){T0Count = 0;P2_0 = ~P2_0;}
}
*/
相关文章:
51单片机-DS18B20(温度传感器)AT24C02(存储芯片) IIC通信-实验2-温度实时监测(可设置阈值)
作者:王开心 座右铭:刻苦专研,百折不挠,千磨万击还坚韧,任尔东西南北风!干就完了!(可交流技术) 主要利用DS18B20芯片去采集温度,通过采集的温度能够自动保存…...

Vue2接入高德地图API实现搜索定位和点击获取经纬度及地址功能
目录 一、申请密钥 二、安装element-ui 三、安装高德地图依赖 四、完整代码 五、运行截图 一、申请密钥 登录高德开放平台,点击我的应用,先添加新应用,然后再添加Key。 如图所示填写对应的信息,系统就会自动生成。 二、安装…...

msvcp140.dll丢失如何解决?msvcp140.dll丢失的多种解决方法
在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行,给用户带来很大的困扰。那么,当我们遇到msvcp140.dll丢失的情况时,应该如何解决呢&a…...

高效财税自动化软件如何提升企业财务工作的效率与准确性
在当今企业运营中,财务管理发挥着核心作用。它不仅涉及企业正常运转和市场决策,还是推动企业向高质量发展迈进的关键动力。面对激烈的市场竞争与科技革新的双重挑战,财务管理亟需进行持续的转型与提升,为企业高质量发展目标的实现…...
Leetcode 3286. Find a Safe Walk Through a Grid
Leetcode 3286. Find a Safe Walk Through a Grid 1. 解题思路2. 代码实现 题目链接:3286. Find a Safe Walk Through a Grid 1. 解题思路 这一题的话思路上就是一个宽度优先遍历,我们按照health进行排序进行宽度优先遍历,看看在health被消…...

shell脚本语法
shell脚本的变量 系统变量 系统变量是操作系统用来存储配置信息的变量,它们可以控制操作系统的行为和程序的运行环境。系统变量的种类和内容取决于操作系统的类型和版本。以下是一些常见的系统变量类别和它们可能包含的内容: 环境变量:这些…...

TCP 拥塞控制:一场网络数据的交通故事
从前有条“高速公路”,我们叫它互联网,而这条公路上的车辆,则是数据包。你可以把 TCP(传输控制协议)想象成一位交通警察,负责管理这些车辆的行驶速度,以防止交通堵塞——也就是网络拥塞。 第一…...

(黑马点评) 五、探店达人系列功能实现
5.1 发布和查看探店笔记 5.1.1 发布探店笔记 这块代码黑马已经完成了,在发布探店笔记界面,有两块内容是需要上传的。一是笔记内容,二是笔记配图。其中笔记配图部分黑马使用的是上传到本地前端服务器上面的。我我觉得可以将图片文件发布在阿里…...
SQLiteDatabase insert or replace数据不生效
在Android开发中,如果您在SQLite数据库中更新了数据,但重启应用后更新的数据不再生效,那么可能的原因有: 更新操作没有正确执行,可能是由于SQL语句错误或者数据库没有正确打开。 更新操作在事务中没有被正确提交。 更…...
基于Python实现一个浪漫烟花秀
为了实现一个类似烟花秀的效果,我们可以通过复杂的粒子系统来模拟烟花的升起、绽放和下落效果。以下是一个示例,旨在创建更为动态和逼真的烟花秀效果。 示例代码 这个代码示例将使用 matplotlib 和 numpy,并实现更丰富的视觉效果࿱…...

电气自动化入门03:安全用电
视频链接:2.1 电工知识:触电原因与防触电措施_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1PJ41117PW/?p4&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.电流对人体的危害 电击:电流通过人体。 电伤:电流热效应…...

【深度学习】(2)--PyTorch框架认识
文章目录 PyTorch框架认识1. Tensor张量定义与特性创建方式 2. 下载数据集下载测试展现下载内容 3. 创建DataLoader(数据加载器)4. 选择处理器5. 神经网络模型构建模型 6. 训练数据训练集数据测试集数据 7. 提高模型学习率 总结 PyTorch框架认识 PyTorc…...

前端面试记录
js 1. 函数式编程 将计算过程视为一系列的函数调用,函数的输出完全由输入决定,不依赖于或改变程序的状态,使得函数式编程的代码更加可预测和易于理解。 函数式编程的三个核心概念:纯函数、高阶函数和柯里化。 高阶函数:函数可以作为参数传…...

裁员了,很严重,大家做好准备吧!
最近刷到这样一个故事: 一个网友在大厂当牛马接近10年,部门优秀员工,业绩一直很稳,没想到,今年公司引进AI降本增效,开始大幅裁员,有些部门一夜之间被连锅端! 上个月果然轮到他了&a…...
uniapp组件uni-datetime-picker选择年月后在ios上日期不显示
uniapp组件uni-datetime-picker选择年月后在ios上日期不显示 操作步骤: ios 选择年月 预期结果: 日期变为选择年月的日期 实际结果: 日期不显示 bug描述: uni-datetime-picker 2.2.22 ios点击年月选择后日期不显示 解决方案 …...
01_快速入门
读取数据 import pandas as pd# df pd.read_excel(https://xxxx/xxx//xx.xslx) # 读取网络数据 # df pd.read_excel(rd:\data\xx.xslx) # 读取本地文件 # 如果是csv文件,用read_csv()函数 df pd.read_csv(seaborn/iris.csv)查看数据 df.head() # 前5条记录 d…...

数据结构之分文件编译学生管理
list.h #ifndef LIST_H_ #define LIST_H_ #define MAX 30 typedef struct {int id;//学号char name[20];//姓名char major[20];//专业int age;//年龄 }student,*Pstudent;typedef struct {student data[MAX];//储存学生信息的数组int len;//统计学生个数 }list,*Plist;Plist c…...

TypeScript入门 (二)控制语句
引言 大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文主要讲解TypeScript中控制语句的部分;希望通过我的知识点总结,能够帮助你更好地…...

MVP 最简可行产品
MVP(最小可行产品)是一种产品开发策略,其主要目的是用最少的时间和资源,开发一个包含最基本必要功能的产品。这样做的目的是能够以最小的成本进入市场,获取用户反馈,再根据反馈逐步优化产品。 MVP是什么 …...

数仓工具:datax
datax可以理解为sqoop的优化版, 速度比sqoop快 因为sqoop底层是map任务,而datax底层是基于内存 DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...