(51单片机)LCD显示数据存储(DS1302时钟模块教学)(LCD1602教程)(独立按键教程)(延时函数教程)(I2C总线认识)(AT24C02认识)

目录

 演示视频:

 源代码

 main.c

LCD1602.c

LCD1602.h

AT24C02.c

AT24C02.h

Key.c

 Key.h

I2C.c

I2C.h

Delay.c 

 Delay.h

 代码解析与教程:

 Dealy模块

 LCD1602模块

 Key模块

I2C总线模块

AT24C02模块 /E2PROM模块

 main模块


 演示视频:

E2PROM数据存储

 源代码

如上图将11个文放在Keli5 中即可,然后烧录在单片机中就行了

烧录软件用的是STC-ISP,不知道怎么安装的可以去看江科大的视频:

【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?p=2&vd_source=ada7b122ae16cc583b4add52ad89fd5e

源代码:

头文件要记得宏定义和重定义,避免重复调用:

#ifndef _Timer0_h_//名字根据文件名定义即可
#define _Timer0_h_//声明函数……#endif

 main.c

#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Key.h"
#include "Delay.h"
#include "AT24C02.h"//获取按键值
unsigned char KeyNum;
//16位的int类型的数
unsigned int Num;//主函数
void main()
{LCD_Init();//初始化LCDLCD_ShowNum(1,1,Num,5);//初始化显示while(1){KeyNum=Key();//获取按键值if(KeyNum==1)	//K1按键,Num自增{Num++;LCD_ShowNum(1,1,Num,5);//LCD显示当前Num}if(KeyNum==2)	//K2按键,Num自减{Num--;LCD_ShowNum(1,1,Num,5);//LCD显示当前Num}if(KeyNum==3)	//K3按键,向AT24C02写入数据{AT24C02_WriteByte(0,Num%256);//获取高8位,存到0字节地址Delay(5);//注意写周期5msAT24C02_WriteByte(1,Num/256);//获取低8位,存到1字节地址Delay(5);LCD_ShowString(2,1,"Write OK");//LCD显示Delay(1000);//显示1秒后消失LCD_ShowString(2,1,"        ");//显示1秒后消失}if(KeyNum==4)	//K4按键,从AT24C02读取数据{Num=AT24C02_ReadByte(0);//返回值Data赋值给Num,获取0字节地址的高8位Num|=AT24C02_ReadByte(1)<<8;//返回值Data赋值给Num,获取1字节地址的低8位,因为Num是16字节,先左移8将前8位变成0,再|(有1即1)将低8位获取出来LCD_ShowNum(1,1,Num,5);//LCD显示当前Num(Data)LCD_ShowString(2,1,"Read OK ");//LCD显示Delay(1000);//显示1秒后消失LCD_ShowString(2,1,"        ");//显示1秒后消失}}
}

LCD1602.c

#include <STC89C5xRC.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()		//@11.0592MHz
{unsigned char i, j;i = 11;j = 190;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');}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__//用户调用函数:
void LCD_Init();//初始化
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);//显示单个字符
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);//显示字符串
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示数字
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);//显示带符号数字
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示十进制数字
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示二进制数字#endif

AT24C02.c

//AT24C02.c#include <STC89C5xRC.H>
#include "I2C.h"#define AT24C02_ADDRESS 0xA0/*** @brief  AT24C02写入一个字节* @param  WordAddress 要写入字节的地址* @param  Data 要写入的数据* @retval 无*/void AT24C02_WriteByte(unsigned char WordAddress,Data){I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Shop();
}/*** @brief  AT24C02读取一个字节* @param  WordAddress 要读出字节的地址* @retval 读出的数据*/unsigned char AT24C02_ReadByte(unsigned char WordAddress){unsigned char Data;I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_Start();I2C_SendByte(AT24C02_ADDRESS|0x01);I2C_ReceiveAck();Data=I2C_ReceiveByte();I2C_SendAck(1);I2C_Shop();return Data;
}

AT24C02.h

//AT24C02.h#ifndef __AT24C02_H__
#define __AT24C02_H__void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif

Key.c

#include <STC89C5xRC.H>
#include "Delay.h"unsigned char Key()//获取独立按键
{unsigned char KeyNumber=0;//进行判断是否摁下按键和防抖操作if(P31==0){Delay(20);while(P31==0);Delay(20);KeyNumber=1;}if(P30==0){Delay(20);while(P30==0);Delay(20);KeyNumber=2;}if(P32==0){Delay(20);while(P32==0);Delay(20);KeyNumber=3;}if(P33==0){Delay(20);while(P33==0);Delay(20);KeyNumber=4;}return KeyNumber;
}

 Key.h

#ifndef _Key_h_
#define _Key_h_unsigned char Key();#endif

I2C.c

//I2C.c#include <STC89C5xRC.H>sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;//I2C开始
void I2C_Start(){I2C_SDA=1;I2C_SCL=1;I2C_SDA=0;I2C_SCL=0;
}//I2C停止
void I2C_Shop(){I2C_SDA=0;I2C_SCL=1;I2C_SDA=1;
}//I2C发送一个字节
void I2C_SendByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){I2C_SDA=Byte&(0x80>>i);I2C_SCL=1;I2C_SCL=0;}
}//I2C接收一个字节
unsigned char I2C_ReceiveByte(){unsigned char i,Byte=0x00;I2C_SDA=1;for(i=0;i<8;i++){I2C_SCL=1;if(I2C_SDA){Byte|=(0x80>>i);}I2C_SCL=0;}return Byte;
}//I2C发送应答
void I2C_SendAck(unsigned char AckBit){I2C_SDA=AckBit;I2C_SCL=1;I2C_SCL=0;
}//I2C接收应答
unsigned char I2C_ReceiveAck(){unsigned char AckBit;I2C_SDA=1;I2C_SCL=1;AckBit=I2C_SDA;I2C_SCL=0;return AckBit;
}

I2C.h

//I2C.h#ifndef __I2C_H__
#define __I2C_H__unsigned char I2C_ReceiveAck();
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveByte();
void I2C_SendByte(unsigned char Byte);
void I2C_Shop();
void I2C_Start();#endif

Delay.c 

//Delay.c#include <STC89C5xRC.H>
#include <INTRINS.H>//延时函数
void Delay(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;while(xms){i = 2;j = 199;do{while (--j);} while (--i);xms--;}
}

 Delay.h

//Delay.h#ifndef __Delay_H__
#define __Delay_H__//延时函数头文件
void Delay(unsigned int xms);
#endif

 代码解析与教程:

 Dealy模块
  • 包含源代码与头文件,不需要知道怎么实现的会用即可,后续使用,直接将头文件和源代码拿过来用即可;

xms是定义的毫秒,1000毫秒就是1秒;模版生成的是1毫秒的,因此xms等于1000

 LCD1602模块
  • 包含源代码与头文件,不需要知道怎么实现的会用即可,后续使用,直接将头文件和源代码拿过来用即可;使用格式:(参考江科大的视频素材)

  • LCD1602相关重要知识:
    • LCD1602有两上下两行显示屏,每行各有16个小显示屏,如上图中的LCD_ShowString(1,3,"Hello"),第一个参数是第一行还是第二行,第2个参数是对应第几行的第几个小显示屏,最后一个是输出的东西,同理,到LCD_ShowNum(1,9,123,3)里,前三个和前面一样,最后一个参数是显示的位数,不够就在前面补0,例如输入1,参数为4,显示就是0001,输入23,参数为3,显示就是023

  • 上图是LCD1602的开发原理模块图,由图可知,P10-P17是控制显示屏的重点;像矩阵那样,S1,由P17和P13控制,同理,其他按键一样,由于开发板限制,我们一般使用列遍历来控制按键,例如:S1,S5,S9,S13他们四个共用P13,所以将其为1列,将P13设定为1,P17设定为0,S1就会亮,其他按键同理。
 Key模块
  • 包含源代码与头文件,不需要知道怎么实现的会用即可,后续使用,直接将头文件和源代码拿过来用即可;

    序号1是按键的防抖操作,不需要理解,有按键的地方直接用即可
    序号2是独立按键控制变量。
    KeyNumber就是返回值,按键K1就返回1,其他同理
I2C总线模块
  • 包含源代码与头文件,需要知道怎么实现的,会用,后续使用,直接将头文件和源代码拿过来用即可;因为这部分比较难,轻度认识理解就行,越深越难
  • 在此之前,我们要认识一下存储器:

  • 本篇博客,以及博主的板子型号(STC89c52rc),用的储存器就是E2PROM储存器,简单介绍一下,RAM就是可读写储存器,SRAM是静态的,容量较大,成本高,类似于我们手机内存,DRAM是动态的,容量较小,成本较低,类似于我们手机的运行内存;ROM按常理来说是不可写的,只能读,但是他比RAM不易丢失,有断电保护,断电后数据不易丢失,因此非常受大家的喜欢,所以在后续的更新中,好多ROM也可以读写了,例如E2PROM。
  • 了解上面之后,I2C总线可以理解成一个传输协议,或者传输方式,规则;作用是将一个机器(主机)的数据传输到另一个机器(从机);来看E2PROM原理图

  • 可以看到SCL,SDA是I2C接口,A0,A1,A2是I2C地址,通过这些东西,将主机(单片机)数据传递到从机(E2PROM);下面来看传输是怎么实现的
  • I2C总线传输时有两大部分,时序结构和数据帧,时序结构就是SCL,SDA这种东西的先后顺序或者说他俩的一些重要关系
  • 时序结构有6个小模块,看图:

这是开始和结束两部分中间框起来的部分是数据确认阶段,高电平是1(高一点的部分),低电平是0(低一点的部分);图中可以看到在数据确认阶段SCL始终为1,SDA也会变化,因此有


//定义SCL,SDA的引脚
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;//I2C开始
void I2C_Start(){I2C_SDA=1;I2C_SCL=1;I2C_SDA=0;I2C_SCL=0;
}//I2C停止
void I2C_Shop(){
//因为开始后SCL=0了,所有这里不需要重复定义了I2C_SDA=0;I2C_SCL=1;I2C_SDA=1;
}

接下来是发送数据,发送一个字节(8个bit),在数据确认期间,SCL先0后1再0,SDA是数据,有可能是1,有可能是0,也会变化,即可发送一个bit,然后循环8次就是一个字节:

//I2C发送一个字节
void I2C_SendByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){I2C_SDA=Byte&(0x80>>i);I2C_SCL=1;I2C_SCL=0;}
}

发送字节是参数Byte,i是循环次数,也是右移几个单位,重点来了:注意看图中的先后顺序,SDA先变化,数据是高位在前,0x80是1000 0000,Byte&(有0即0)0x80就是保留Byte的第一位(最高位),其他全变0;然后变化SCL0,1,0;循环八次

接下来是接收数据,接收一个字节(8个bit),在数据确认期间,SCL先0后1再0,SDA是数据,有可能是1,有可能是0,也会变化,即可发送一个bit,然后循环8次就是一个字节:

//I2C接收一个字节
unsigned char I2C_ReceiveByte(){unsigned char i,Byte=0x00;I2C_SDA=1;for(i=0;i<8;i++){if(I2C_SDA){Byte|=(0x80>>i);}I2C_SCL=1;I2C_SCL=0;}return Byte;
}

接收字节是无参数,返回值是Data,i是循环次数,也是右移几个单位,重点来了:注意,主机接收之前需要释放SDA(使SDA=1);注意看图中的先后顺序,SDA先变化,数据是高位在前,0x80是1000 0000,Byte&(有0即0)0x80就是保留Byte的第一位(最高位),其他全变0;然后变化SCL0,1,0;循环八次


接下来是发送应答和就收应答,作用就是在发送和接收时进行一个反馈,告诉你发送或者接收成功。
 
//I2C发送应答
void I2C_SendAck(unsigned char AckBit){I2C_SDA=AckBit;I2C_SCL=1;I2C_SCL=0;
}//I2C接收应答
unsigned char I2C_ReceiveAck(){unsigned char AckBit;I2C_SDA=1;AckBit=I2C_SDA;I2C_SCL=1;I2C_SCL=0;return AckBit;
}
发送应答参数AckBit是应答数据,0就是表示应答,1是不应答; 注意看图中的先后顺序,SDA先变化,将应答数据赋值给SDA;然后变化SCL0,1,0;
接收应答无参数,返回值是AckBit是应答数据,0就是表示应答,1是不应答; 注意,主机接收之前需要释放SDA(使SDA=1);注意看图中的先后顺序,SDA先变化将SDA赋值给AckBit;然后变化SCL0,1,0;
  • 了解时序结构之后,来看数据帧,也就是数据是怎么在I2C中传输的:

发送一帧数据是有I2C时序结构的6个小模块组成的,图中都标注了;需要注意的是要告诉I2C总线向谁发送,也就是要先发送从机地址,从机地址最后一个是告诉你是读还是写;

接收一帧数据是有I2C时序结构的6个小模块组成的,图中都标注了;需要注意的是要告诉I2C总线向谁接收,也就是要先发送从机地址,从机地址最后一个是告诉你是读还是写;注意最后一个发送应答是1,表示非应答

复合格式数据是有I2C时序结构的6个小模块组成的,图中都标注了;需要注意的是要告诉I2C总线向谁发送并接收,也就是要先发送从机地址,从机地址最后一个是告诉你是读还是写;注意最后一个发送应答是1,表示非应答

AT24C02模块 /E2PROM模块
  • 包含源代码与头文件,需要知道怎么实现的,会用,后续使用,直接将头文件和源代码拿过来用即可;因为这部分比较难,轻度认识理解就行,越深越难
  • AT24C02是E2PROM模块中的一小块,可以理解上述中所提到的从机主机就是单片机,因此从机地址就是AT24C02地址;

字节写,随机读数据帧是有I2C时序结构的6个小模块组成的,图中不再标注了;需要注意的是要告诉I2C总线读还是写,也就是要发送从机地址SLAVE ADDRESS,从机地址最后一个是告诉你是读还是写;还有一个就是发送存储字节地址WORD ADDRESS;注意最后一个发送应答是1,表示非应答

//AT24C02.c#include <STC89C5xRC.H>
#include "I2C.h"#define AT24C02_ADDRESS 0xA0/*** @brief  AT24C02写入一个字节* @param  WordAddress 要写入字节的地址* @param  Data 要写入的数据* @retval 无*/void AT24C02_WriteByte(unsigned char WordAddress,Data){I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Shop();
}/*** @brief  AT24C02读取一个字节* @param  WordAddress 要读出字节的地址* @retval 读出的数据*/unsigned char AT24C02_ReadByte(unsigned char WordAddress){unsigned char Data;I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_Start();I2C_SendByte(AT24C02_ADDRESS|0x01);I2C_ReceiveAck();Data=I2C_ReceiveByte();I2C_SendAck(1);I2C_Shop();return Data;
}

按照图中的I2C总线时序结构,依次调用函数,即可实现

注意写周期是5ms,意味着每次写完后要延时5ms;

 main模块
  • 注释写的很清楚,这里不做解释了
#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Key.h"
#include "Delay.h"
#include "AT24C02.h"//获取按键值
unsigned char KeyNum;
//16位的int类型的数
unsigned int Num;//主函数
void main()
{LCD_Init();//初始化LCDLCD_ShowNum(1,1,Num,5);//初始化显示while(1){KeyNum=Key();//获取按键值if(KeyNum==1)	//K1按键,Num自增{Num++;LCD_ShowNum(1,1,Num,5);//LCD显示当前Num}if(KeyNum==2)	//K2按键,Num自减{Num--;LCD_ShowNum(1,1,Num,5);//LCD显示当前Num}if(KeyNum==3)	//K3按键,向AT24C02写入数据{AT24C02_WriteByte(0,Num%256);//获取高8位,存到0字节地址Delay(5);//注意写周期5msAT24C02_WriteByte(1,Num/256);//获取低8位,存到1字节地址Delay(5);LCD_ShowString(2,1,"Write OK");//LCD显示Delay(1000);//显示1秒后消失LCD_ShowString(2,1,"        ");//显示1秒后消失}if(KeyNum==4)	//K4按键,从AT24C02读取数据{Num=AT24C02_ReadByte(0);//返回值Data赋值给Num,获取0字节地址的高8位Num|=AT24C02_ReadByte(1)<<8;//返回值Data赋值给Num,获取1字节地址的低8位,因为Num是16字节,先左移8将前8位变成0,再|(有1即1)将低8位获取出来LCD_ShowNum(1,1,Num,5);//LCD显示当前Num(Data)LCD_ShowString(2,1,"Read OK ");//LCD显示Delay(1000);//显示1秒后消失LCD_ShowString(2,1,"        ");//显示1秒后消失}}
}

 注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!

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

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

相关文章

电子病历高质量语料库构建方法与架构项目(数据遗忘篇)

引言 在人工智能与医疗健康的深度融合时代,医疗数据的价值与风险并存。跨机构和平台的医疗数据共享对于推动医学研究、提高诊断精度和实现个性化治疗至关重要,但同时也带来了前所未有的隐私挑战。先进的AI技术可以从理论上去标识化的医疗扫描中重新识别个人身份,例如从MRI数…

CentOS创建swap内存

服务器版本为CentOS7 一、检查现有 swap 空间 sudo swapon --show如果系统中没有 swap 空间或者现有的 swap 空间不足&#xff0c;可以继续后续步骤来创建 swap 空间。 二、创建 swap 文件&#xff08;推荐 2GB 作为示例&#xff09; sudo dd if/dev/zero of/swapfile bs1M …

在Android中如何使用Protobuf上传协议

在 Android 中使用 Protobuf&#xff08;Protocol Buffers&#xff09;主要分为以下几个步骤&#xff1a; ✅ 1. 添加 Protobuf 插件和依赖 在项目的 build.gradle&#xff08;Project 级&#xff09;文件中添加 Google 的 Maven 仓库&#xff08;通常默认已有&#xff09;&am…

Android学习总结之ANR问题

一、ANR 基础概念与核心原理&#xff08;必考题&#xff09; 1. 什么是 ANR&#xff1f;为什么会发生 ANR&#xff1f; 答案要点&#xff1a; 定义&#xff1a;ANR&#xff08;Application Not Responding&#xff09;即应用无响应&#xff0c;是 Android 系统检测到主线程&…

视频监控从安装到优化的技术指南,视频汇聚系统EasyCVR智能安防系统构建之道

在当今数字化安防时代&#xff0c;监控系统的安装与配置对于保障各类场所的安全起着至关重要的作用。从前期规划到实际安装&#xff0c;再到后期的功能实现与维护&#xff0c;每一个环节都不容小觑。本文将详细阐述监控安装过程中的关键要点&#xff0c;并结合EasyCVR平台功能&…

如何避免IDEA每次打开新项目都重复配置Maven?

每次打开新项目都要重新设置Maven路径&#xff1f;每次导入工程都要手动调整settings.xml&#xff1f;如果你也受够了IDEA这种“健忘”行为&#xff0c;那么这篇文章就是为你准备的&#xff01;今天我们就来彻底解决这个问题&#xff0c;让IDEA记住你的Maven配置&#xff0c;一…

PostgesSQL外部数据封装FDW

PostgesSQL外部数据封装FDW 1. FDW外部数据配置&#xff08;单表&#xff09;1.1 远端数据库创建测试表1.2 安装扩展postges\_fdw1.3 创建外部服务SERVER1.4 创建用户映射USER MAPPING1.5 创建远程表FOREIGN TABLE1.6 数据库更新测试 2. FDW外部数据配置&#xff08;用户&#…

策略模式(Strategy Pattern)详解

文章目录 1. 什么是策略模式&#xff1f;2. 为什么需要策略模式&#xff1f;3. 策略模式的核心概念3.1 策略&#xff08;Strategy&#xff09;3.2 具体策略&#xff08;Concrete Strategy&#xff09;3.3 上下文&#xff08;Context&#xff09; 4. 策略模式的结构5. 策略模式的…

在 Vue3 中封装的 Axios 实例中,若需要为部分接口提供手动取消请求的功能

核心思路 封装接口时返回 Promise 和 abort 方法&#xff1a; 为需要支持取消的接口返回一个对象&#xff0c;包含 promise 和 abort 方法&#xff0c;用户可通过 abort 主动中断请求。使用 AbortController 或 CancelToken&#xff1a; 推荐 AbortController&#xff08;浏览…

Flink介绍——实时计算核心论文之Dataflow论文详解

引入 在过去的几篇文章里&#xff0c;我们看到了大数据的流式处理系统是如何一步一步进化的。从最早出现的S4&#xff0c;到能够做到“至少一次”处理的Storm&#xff0c;最后是能够做到“正好一次”数据处理的MillWheel。我们会发现&#xff0c;这些流式处理框架&#xff0c;…

Python自动化解决滑块验证码的最佳实践

1. 引言&#xff1a;滑块验证码的挑战与自动化需求 滑块验证码&#xff08;Slider CAPTCHA&#xff09;是当前互联网广泛使用的反爬机制之一&#xff0c;它要求用户手动拖动滑块到指定位置以完成验证。这种验证方式可以有效阻止简单的自动化脚本&#xff0c;但对爬虫开发者来说…

路由与OSPF学习

【路由是跨网段通讯的必要条件】 路由指的是在网络中&#xff0c;数据包从源主机传输到目的主机的路径选择过程。 路由通常涉及以下几个关键元素&#xff1a; 1.路由器&#xff1a;是一种网络设备&#xff0c;负责将数据包从一个网络传输到另一个网络。路由器根据路由表来决定…

(done) 吴恩达版提示词工程 5. 推理 (情绪分类,控制输出格式,输出 JSON,集成多个任务,文本主题推断和索引,主题内容提醒)

url: https://www.bilibili.com/video/BV1Z14y1Z7LJ?spm_id_from333.788.videopod.episodes&vd_source7a1a0bc74158c6993c7355c5490fc600&p2 别人的笔记 url: https://zhuanlan.zhihu.com/p/626966526 5. 推理任务&#xff08;Inferring&#xff09; 这个视频是关于…

MySQL VS SQL Server:优缺点全解析

数据库选型、企业协作、技术生态、云数据库 1.1 MySQL优缺点分析 优点 开源免费 社区版完全免费&#xff0c;适合预算有限的企业 允许修改源码定制功能&#xff08;需遵守GPL协议&#xff09; 跨平台兼容性 支持Windows/Linux/macOS&#xff0c;适配混合环境部署 云服务商…

Pycharm 代理配置

Pycharm 代理配置 文章目录 Pycharm 代理配置1. 设置系统代理1.1 作用范围1.2 使用场景1.3 设置步骤 2. 设置 python 运行/调试代理2.1 作用范围2.2 使用场景2.3 设置步骤 Pycharm 工具作为一款强大的 IDE&#xff0c;其代理配置在实际开发中也是必不可少的&#xff0c;下面介绍…

maven打包时配置多环境参数

1. pom配置 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

国产三维CAD皇冠CAD在机械及汽车零部件设计建模教程:斜滑动轴承

在线解读『斜滑动轴承』的三维建模流程&#xff0c;讲解布尔运算、旋转凸台/基体、异型导向孔、装饰螺纹线等操作技巧&#xff0c;一起来皇冠CAD&#xff08;CrownCAD&#xff09;直播间学习制作步骤吧&#xff01; 斜滑动轴承凭借其独特的工作原理和广泛的应用领域&#xff0c…

linux(操作系统概述和虚拟机的安装)

1.操作系统 一、主流服务器操作系统 Windows server 市场地位&#xff1a;适合传统企业&#xff08;主要以中小型企业、金融机构和教育机构为主&#xff09; 核心特点&#xff1a; 企业级功能&#xff1a;活动目录、组策略、IIS/Web服务器、Exchange邮件服务 易用性&#xff1a…

鸿蒙生态新利器:华为ArkUI-X混合开发框架深度解析

鸿蒙生态新利器&#xff1a;华为ArkUI-X混合开发框架深度解析 作者&#xff1a;王老汉 | 鸿蒙生态开发者 | 2025年4月 &#x1f4e2; 前言&#xff1a;开发者们的新机遇 各位鸿蒙开发者朋友们&#xff0c;是否还在为多平台开发重复造轮子而苦恼&#xff1f;今天给大家介绍一位…

数据结构初阶:二叉树(四)

概述&#xff1a;本篇博客主要介绍链式结构二叉树的实现。 目录 1.实现链式结构二叉树 1.1 二叉树的头文件&#xff08;tree.h&#xff09; 1.2 创建二叉树 1.3 前中后序遍历 1.3.1 遍历规则 1.3.1.1 前序遍历代码实现 1.3.1.2 中序遍历代码实现 1.3.1.3 后序遍历代…