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等各种异构数据源之间稳定…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...