51单片机——I2C-EEPROM
I2C:总线标准或通信协议
EEPROM:AT24C02芯片
开发板板载了1个EEPROM模块,可实现IIC通信
1、EEPROM模块电路(AT24C02)

芯片的SCL和SDA管脚是连接在单片机的P2.1和P2.0上
2、I2C介绍
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器(MCU)及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点
I2C 总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL
2.1 I2C物理层
I2C通信设备常用的连接方式如下图所示:

特点(了解一下即可):
(1)它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个I2C通讯总线中,可连接多个I2C通讯设备,支持多个通讯主机及多个通讯从机
(2)一个I2C总线只使用两条总线线路,一条双向串行数据线(SDA),一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步
(3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问
(4)总线通过上拉电阻接到电源。当I2C设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平
(5)多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线
(6)具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达 3.4Mbit/s,但目前大多I2C设备尚不支持高速模式
(7)连接到相同总线的IC数量受到总线的最大电容400pF限制(接5-6个没有问题)
2.2 I2C协议层(作用于MCU)
I2C的协议定义了通信的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节
2.2.1 数据有效性规定
I2C总线进行数据传送时,时钟(SCL)信号为高电平期间,数据(SDA)线上的数据必须保持稳定;只有在时钟(SCL)线上的信号为低电平期间,数据(SDA)线上的高电平或低电平状态才允许变化。如下图所示:

每次数据传输都以字节为单位,每次传输的字节数不受限制
每一个字节必须保证是8位长度。数据传送时,先传送最高位
2.2.1.1 读数据的代码
SCL为高电平时才能读数据
//6、读字节
u8 iic_read_byte(u8 ack){
u8 i=0,receive=0;
for(i=0;i<8;i++){
IIC_SCL=0; //开始时SCL为低电平
delay_10us(1); //有一个延时,是因为高低电平变化时,会有一个变化时间,需要延时一下
IIC_SCL=1; //往后走变为高电平
receive<<=1;
if(IIC_SDA==1){
receive++;
}
delay_10us(1);
}
if(!ack){
iic_ack();
}else{
iic_nack();
}
return receive;
}
2.2.1.2 写数据的代码
void iic_write_byte(u8 dat){
u8 i=0;
IIC_SCL=0; //为0时,数据可以改变
//循环8次,将一个字节传出去
//要求:先传高位,再传低位
for(i=0;i<8;i++){
if((dat&0x80)>0){
IIC_SDA=1;
}else{
IIC_SDA=0;
}
dat<<=1; //把次高位变为最高位
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
delay_10us(1);
}
}
2.2.2 起始和停止信号
起始条件:SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号
终止条件:SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号
如下图所示:

2.2.2.1 起始信号
void iic_start(){
IIC_SDA=1;
IIC_SCL=1;
delay_10us(1);
IIC_SDA=0; //SDA先变为低电平,先写SDA
// delay_10us(1); //可以加,也可以不加
IIC_SCL=0; //拉低后,就准备发送和接收数据
// delay_10us(1); //可以加,也可以不加
}
2.2.2.2 停止信号
void iic_stop(){
IIC_SDA=0;
IIC_SCL=1;
delay_10us(1);
IIC_SDA=1;
IIC_SCL=1; //写不写都可以
}
2.2.3 应答响应
每当发送器件传输完一个字节(长度:8)的数据后,后面必须紧跟一个校验位,这个校验位是接收端通过控制 SDA(数据线)来实现的,以提醒发送端数据我这边已经接收完成,数据传送可以继续进行。这个校验位其实就是数据或地址传输过程中的响应
响应包括“应答(ACK)”和“非应答(NACK)”两种信号
作为数据接收端时,当设备(无论主从机)接收到I2C传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答(ACK)”信号即特定的低电平脉冲, 发送方会继续发送下一个数据
若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号即特定的高电平脉冲,发送方接收到该信号后会产生一个停止信号,结束信号传输
应答响应时序图如下图所示:

发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据1表示非应答(主机在接收之前,需要释放SDA)
2.2.3.1 应答0
void iic_ack(){
IIC_SCL=0;
IIC_SDA=0; //应答
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
2.2.3.2 非应答1
void iic_nack(){
IIC_SCL=0;
IIC_SDA=1; //非应答
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
2.2.3.3 等待应答
返回值为0应答;返回值为1非应答
u8 iic_wait_ack(){
u8 time_temp=0; //注意:定义变量时放在上方,否则容易出现问题
IIC_SCL=1;
delay_10us(1);
//意外情况,没有应答
while(IIC_SDA){ //等待IIC_SDA出现低电平
time_temp++;
if(time_temp>100){ //超时了,强制退出
iic_stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}
这些信号中,起始信号是必需的,结束信号和应答信号都可以不要
2.2.4 总线的寻址方式
(1)I2C总线寻址按照从机地址位数可分为两种,一种是7位,另一种是10位。采用7位的寻址字节(寻址字节是起始信号后的第一个字节)的位定义如下图所示:

D7-D1位组成从机的地址。D0位是数据传送方向位,为“0”时表示主机向从机写数据,为“1”时表示主机由从机读数据
(2)AT24C02器件地址为7位,高4位固定为1010,低3位由A0/A1/A2信号线的电平决定。因为传输地址或数据是以字节为单位传送的,当传送地址时,器件地址占7位,还有最后一位(最低位R/W)用来选择读写方向,它与地址无关。其格式如下图所示:
![]()
如果要对芯片进行写操作时,R/W 即为0,写器件地址即为0XA0;如果要对芯片进行读操作时,R/W 即为1,此时读器件地址为0XA1
(1)和(2)连起来看,两个图代表的意思一样
2.2.5 数据传输
在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/W),用“0”表示主机发送(写)数据(W),“1”表示主机接收(读)数据(R)
2.2.5.1 写数据
有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A 表示应答,A 非表示非应答(高电平)。S表示起始信号,P表示终止信号


void at24c02_write_one_byte(u8 addr,u8 dat){ //addr:at24c02的地址
iic_start(); //S
iic_write_byte(0xa0); //1010 0000 //从机地址和0
iic_wait_ack(); //A
iic_write_byte(addr); //指定地址 //寄存器(at24c02)地址
iic_wait_ack(); //A
iic_write_byte(dat); //数据
iic_wait_ack(); //A/A非
iic_stop(); //P
delay_ms(10);
}
2.2.5.2 读数据
有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A 表示应答,A 非表示非应答(高电平)。S表示起始信号,P表示终止信号

u8 at24c02_read_one_byte(u8 addr){ //addr:at24c02的数据地址
u8 temp=0;
iic_start(); //S
iic_write_byte(0xa0); //1010 0000 //从机地址和0
iic_wait_ack(); //A
iic_write_byte(addr); //指定地址 //寄存器(at24c02)地址
iic_wait_ack(); //A/A非
iic_start(); //S
iic_write_byte(0xa1); //1010 0001 //从机地址和1
iic_wait_ack(); //A
temp=iic_read_byte(1); //读时从当前地址开始读(因为上方已经指定过at24c02的地址了,所以不需要再次指定at24c02的地址 )
iic_stop(); //P
return temp;
}
3、软件设计
3.1 创建多文件工程
3.1.1 创建文件夹
在电脑上创建一个实验文件夹,为了与教程配套,这里命名为“I2C-EEPROM实验”,然后在该文件夹内新建App、Public、User三个文件夹,如下图所示:

Listings和Objects是软件自动生成的
App文件夹:用于存放外设驱动文件,如LED、数码管、定时器等(24c02、iic、key、smg四个文件夹)
Public文件夹:用于存放51单片机公共的文件,如延时、51头文件、变量类型重定义等。
User文件夹:用于存放用户主函数文件,如main.c
3.1.2 新建工程
首先打开KEILC51软件,新建一个工程,将工程命名为template并保存在“I2C-EEPROM实验”文件夹下,然后选择芯片类型为“AT89C52”,不使用系统创建启动文件


3.1.3 向工程添加文件
(1)将含有.c文件的文件夹添加到工程中,这里我在工程中创建3组,User、App、Publi,通常在工程组的命名与创建的文件夹名保持一致,方便查找到源文件位置

(2)点击下图中的图标,创建新文件,Ctrl+S将文件重命名,并保存到对应的文件夹中
例如:创建新文件,Ctrl+S将文件重命名为public.c,并保存到public文件夹中

(3)这样每一个文件夹中都有一个.c和一个.h文件(文件名和文件夹名一样),之后需要将建好的文件添加到(1)创建的工程中

App:24c02.c、iic.c、key.c、smg.c
Public:public.c
User:main.c

3.1.4 配置魔术棒选项卡
(1)点击下图中的图标

(2) 点击Output选项卡,将CreateHEXFile选项勾上

(3)点击C51选项卡,将前面添加到工程组中的文件路径包括进来,否则程序中调用其他文件夹的头文件则会报错找不到头文件路径



3.2 实验代码
要实现的功能是:系统运行时,数码管右3位显示0,按K1键将数据写入到EEPROM内保存,按K2键读取EEPROM内保存的数据,按K3键显示数据加1,按K4键显示数据清零,最大能写入的数据是255
一般我们以文件形式存放对应功能的驱动程序时,会创建2个文件,一个是.c源文件,另一个是.h头文件。源文件(.c)通常存放的是外设的驱动程序,比如按键检测函数;而头文件(.h)通常用 来存放管脚定义、变量声明、函数声明
3.2.1 public文件
3.2.1.1 public.h
//头文件中放置函数的声明、全局变量的定义
#ifndef _public_H
#define _public_H
#include "reg52.h"
//全局变量
typedef unsigned int u16;
typedef unsigned char u8;
//两个延迟函数声明
void delay_10us(u16 us);
void delay_ms(u16 ms);
#endif
在头文件的开头,使用“#ifndef”关键字,判断标号“_public_H”是否被定义,若没有被定义,则从“#ifndef”至“#endif”关键字之间的内容都有效
这个头文件(public.h文件)若被其它文件“#include”,它就会被包含到其该文件中,且头文件中紧接着使用“#define”关键字定义上面判断的标号“_public_H”。当这个头文件被同一个文件第二次“#include”包含的时候,由于有了第一次包含中的“#define _public_H” 定义,这时再判断“#ifndef _public_H”,判断的结果就是假了,从“#ifndef” 至“#endif”之间的内容都无效,从而防止了同一个头文件被包含多次,编译时就不会出现“redefine(重复定义)”的错误了
3.2.1.2 public.c
#include "public.h"
void delay_10us(u16 us){
while(us--);
}
void delay_ms(u16 ms){
u16 i=0,j=0;
for(i=0;i<ms;i++){
for(j=0;j<110;j++);
}
}
3.2.2 独立按键
3.2.2.1 key.h文件
#ifndef _key_H
#define _key_H
#include "public.h"
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
u16 key_scan(u16 mode);
#endif
3.2.2.2 key.c文件
#include "key.h"
u16 key_scan(u16 mode){
static u16 key=1;
if(mode==1){
key=1;
}
if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)){
delay_10us(1000);
key=0;
if(KEY1==0){
return 1;
}else if(KEY2==0){
return 2;
}else if(KEY3==0){
return 3;
}else if(KEY4==0){
return 4;
}
}else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1){
key=1;
return 0;
}
}
3.2.3 动态数码管
3.2.3.1 smg.h
#ifndef _smg_H
#define _smg_H
#include "public.h"
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
#define SMG_A_DP_PORT P0
extern u8 gsmg_code[];
void smg_display(u8 save_buff[],u8 pos);
#endif
3.2.3.2 smg.c
#include "smg.h"
u8 gsmg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//save_buff是一个u8类型的数组,方便外部传入要显示的数据
//pos是数码管从左开始第几个位置开始显示,取值范围是1-8
void smg_display(u8 save_buff[],u8 pos){
u16 i=0;
u16 pos_temp=pos-1;
for(i=pos_temp;i<8;i++){
//位选
switch(i){
case 0:
LSC=1,LSB=1,LSA=1; //7
break;
case 1:
LSC=1,LSB=1,LSA=0; //6
break;
case 2:
LSC=1,LSB=0,LSA=1; //5
break;
case 3:
LSC=1,LSB=0,LSA=0; //4
break;
case 4:
LSC=0,LSB=1,LSA=1; //3
break;
case 5:
LSC=0,LSB=1,LSA=0; //2
break;
case 6:
LSC=0,LSB=0,LSA=1; //1
break;
case 7:
LSC=0,LSB=0,LSA=0; //0
break;
}
SMG_A_DP_PORT=gsmg_code[save_buff[i-pos_temp]]; //save_buff[?](?:0、1、2)
delay_10us(100);
SMG_A_DP_PORT=0x00; //消隐
}
}
3.2.4 I2C读写字节函数
3.2.4.1 iic.h
#ifndef _iic_H
#define _iic_H
#include "public.h"
//定义管脚
sbit IIC_SCL=P2^1;
sbit IIC_SDA=P2^0;//iic协议层的函数
//1、起始信号
void iic_start();
//2、停止信号
void iic_stop();
//3、应答
void iic_ack();
//4、非应答
void iic_nack();
//5、等待应答
u8 iic_wait_ack();
//6、读字节
u8 iic_read_byte(u8 ack);
//7、写字节
void iic_write_byte(u8 dat);
#endif
3.2.4.2 iic.c
#include "iic.h"
//iic协议层的函数//1、起始信号
void iic_start(){
IIC_SDA=1;
IIC_SCL=1;
delay_10us(1);
IIC_SDA=0;
// delay_10us(1); //可以加,也可以不加
IIC_SCL=0; //拉低后,就准备发送和接收数据
// delay_10us(1); //可以加,也可以不加
}//2、停止信号
void iic_stop(){
IIC_SDA=0;
IIC_SCL=1;
delay_10us(1);
IIC_SDA=1;
IIC_SCL=1; //写不写都可以
}//3、应答
void iic_ack(){
IIC_SCL=0;
IIC_SDA=0; //应答
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}//4、非应答
void iic_nack(){
IIC_SCL=0;
IIC_SDA=1; //非应答
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}//5、等待应答,返回值为0应答;返回值为1非应答
u8 iic_wait_ack(){
u8 time_temp=0; //注意:定义变量时放在上方,否则容易出现问题
IIC_SCL=1;
delay_10us(1);
//意外情况,没有应答
while(IIC_SDA){ //等待IIC_SDA出现低电平
time_temp++;
if(time_temp>100){ //超时了,强制退出
iic_stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}//6、读字节
u8 iic_read_byte(u8 ack){
u8 i=0,receive=0;
for(i=0;i<8;i++){
IIC_SCL=0;
delay_10us(1);
IIC_SCL=1;
receive<<=1;
if(IIC_SDA==1){
receive++;
}
delay_10us(1);
}
//注意:看看测试时和案例是否一样(没有区别)
if(!ack){
iic_ack();
}else{
iic_nack();
}
return receive;
}
//7、写字节
void iic_write_byte(u8 dat){
u8 i=0;
IIC_SCL=0; //为0时,数据可以改变
//循环8次,将一个字节传出去
//要求:先传高位,再传低位
for(i=0;i<8;i++){
if((dat&0x80)>0){
IIC_SDA=1;
}else{
IIC_SDA=0;
}
dat<<=1; //把次高位变为最高位
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
delay_10us(1);
}
}
3.2.5 AT24C02读写字节函数
3.2.5.1 at24c02.h
#ifndef _at24c02_H
#define _at24c02_H
#include "public.h"
#include "iic.h"
//写入数据函数
void at24c02_write_one_byte(u8 addr,u8 dat);
//读数据函数
u8 at24c02_read_one_byte(u8 addr);
#endif
3.2.5.2 at24c02.c
#include "at24c02.h"
//写
void at24c02_write_one_byte(u8 addr,u8 dat){ //addr:at24c02的地址
iic_start();
iic_write_byte(0xa0); //1010 0000
iic_wait_ack();
iic_write_byte(addr); //指定地址
iic_wait_ack();
iic_write_byte(dat);
iic_wait_ack();
iic_stop();
delay_ms(10);
}//读
u8 at24c02_read_one_byte(u8 addr){ //addr:at24c02的数据地址
u8 temp=0;
iic_start();
iic_write_byte(0xa0);
iic_wait_ack();
iic_write_byte(addr); //指定地址
iic_wait_ack();
iic_start();
iic_write_byte(0xa1);
iic_wait_ack();
temp=iic_read_byte(1); //读时从当前地址开始读
iic_stop();
return temp;
}
3.2.6 main.c
#include "public.h"
#include "smg.h"
#include "key.h"
#include "iic.h"
#include "at24c02.h"
#define EEPROM_ADDRESS 0 //不超过255即可
/*
系统运行时,数码管右3位显示0
按K1键将数据写入到EEPROM内保存
按K2键读取EEPROM内保存的数据
按K3键显示数据加1,最大能写入的数据是255(0-255)
按K4键显示数据清零
*/
void main(){
u8 key_temp=0;
u8 save_value=0; //可以不设为0
u8 save_buff[3];
while(1){
key_temp=key_scan(0);
if(key_temp==1){ //保存数据(写)
at24c02_write_one_byte(EEPROM_ADDRESS,save_value);
}else if(key_temp==2){ //读取数据
save_value=at24c02_read_one_byte(EEPROM_ADDRESS);
}else if(key_temp==3){ //数据+1
save_value++;
if(save_value==255){
save_value=255;
}
}else if(key_temp==4){ //数据清零
save_value=0;
}
//save_value是一个十进制的值
//让数码管显示数据,需要得到save_value个位、十位和百位的值
save_buff[0]=save_value/100; //百位
save_buff[1]=save_value/10%10; //十位
save_buff[2]=save_value%10; //个位
smg_display(save_buff,6);
}
}
相关文章:
51单片机——I2C-EEPROM
I2C:总线标准或通信协议 EEPROM:AT24C02芯片 开发板板载了1个EEPROM模块,可实现IIC通信 1、EEPROM模块电路(AT24C02) 芯片的SCL和SDA管脚是连接在单片机的P2.1和P2.0上 2、I2C介绍 I2C(Interÿ…...
R语言的语法糖
R语言的语法糖 引言 在编程语言中,所谓的“语法糖”是指那些使得程序员能够以更简洁、直观的方式书写代码的语法形式。R语言作为一种用于统计分析和数据可视化的编程语言,具有丰富的功能和灵活的语法。本文将深入探讨R语言中的语法糖,帮助读…...
【算法学习笔记】30:埃氏筛(Sieve of Eratosthenes)和线性筛(Linear Sieve)
测试题目:AcWing 868. 筛质数 埃氏筛(Sieve of Eratosthenes) 如果 i i i是素数,每次把 i i i的倍数都筛掉,存在重复筛选,时间复杂度 n ⋅ l o g ( l o g n ) n \cdot log(logn) n⋅log(logn)。 #includ…...
【AscendC】tiling方案设计不当引起的一个时隐时现的bug
在设计tiling方案时,通常会考虑到非对齐的场景,对输入数据进行补全操作从而使得非对齐场景也能正确的完成计算。但在某些算子的实现过程中,沿用上述操作却会造成数据的错误计算,且这种错误出现与否取决于随机生成的测试数据质量。…...
视频转码对画质有影响吗?视频融合平台EasyCVR支持哪些转码格式?
视频转码过程是将视频文件从一种编码格式转换为另一种格式的过程,这一过程在现代数字媒体中扮演着至关重要的角色。众所周知,视频转码不仅仅是简单的格式转换,它涉及多个关键参数的改变,例如视频编码格式、比特率、分辨率以及帧率…...
工业视觉2-相机选型
工业视觉2-相机选型 一、按芯片类型二、按传感器结构特征三、按扫描方式四、按分辨率大小五、按输出信号六、按输出色彩接口类型 这张图片对工业相机的分类方式进行了总结,具体如下: 一、按芯片类型 CCD相机:采用电荷耦合器件(CC…...
基于SpringBoot+Vue的健身房管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 随着现代生活节奏的加快,人们对健康的需求日益增强,健身房行业因此迎来了蓬勃的发展。然而,传统的健身房管理方式逐渐暴露出效率低下、会员信息管理混乱、课程安排不灵活等问题。为了解决这些…...
leetcode 面试经典 150 题:快乐数
链接快乐数题序号202题型数组解题方法哈希表难度简单熟练度✅✅✅✅ 题目 编写一个算法来判断一个数 n 是不是快乐数。 [快乐数] 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1࿰…...
Leetcode 279. 完全平方数 动态规划 完全背包问题
原题链接:Leetcode 279. 完全平方数 class Solution { public:int numSquares(int n) {vector<int> dp(n 1, 0);for (int i 1; i < n; i) {int tmp INT_MAX;for (int j 1; j * j < i; j) {tmp min(tmp, dp[i - j * j]);}dp[i] tmp 1;}return dp[…...
python学opencv|读取图像(三十三)阈值处理图像-限定像素
【1】引言 前序我们已经掌握分解图像的通道,设置各个通道的RGB值,相关文章包括且不限于: python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分-CSDN博客 python学opencv|读取图像(十五)B…...
QT Quick QML 实例之椭圆投影,旋转
文章目录 一、前言二、演示三、部分代码与分析 QML 其它文章请点击这里: QT QUICK QML 学习笔记 国际站点 GitHub: https://github.com/chenchuhan 国内站点 Gitee : https://gitee.com/chuck_chee 一、前言 此 Demo 主要用于无人机吊舱视角的模拟…...
炸砖块游戏的最终图案
描述 小红正在玩一个“炸砖块”游戏,游戏的规则如下:初始有一个 n * m 的砖块矩阵。小红会炸 k 次,每次会向一个位置投炸弹,如果这个位置有一个砖块,则砖块消失,上方的砖块向下落。小红希望你画出最终砖块的图案。 输入描述 第一行输入三个正整数 n, m, k,代表矩阵的行…...
LLM的实验平台有哪些:快速搭建测试大语言模型
LLM的实验平台有哪些:快速搭建测试大语言模型 目录 LLM的实验平台有哪些:快速搭建测试大语言模型低代码平台工程观测平台本地应用平台在线编程竞技场性能排名代码质量评估开源框架Hugging Face是一个机器学习和数据科学平台及社区主要功能开源工具与库应用场景优势低代码平台…...
python3GUI--大屏可视化-XX产业大数据指挥舱(附下载地址) By:PyQt5
文章目录 一.前言二.预览三.软件开发心得1.使用方法2.UI设计3.代码架构4.项目结构 四.代码片段分享1.图片平滑缩放组件2.滚动日志组件 五.心得体会 大小:35.0 M,软件安装包放在了这里! 本软件未…...
.NET 9.0 的 Blazor Web App 项目中 Hash 变换(MD5、Pbkdf2) 使用备忘
一、生成 string 对应的 MD5 码 /// <summary>/// 生成 string 对应的 MD5 码/// </summary>/// <param name"str">需要转换的字符串 string:用于登录认证时,str username 线下传递的key DateTime.Now.Ticks.ToString() …...
uniapp 抖音小程序 getUserProfile:fail must be invoked by user tap gesture
项目场景: uniapp 抖音小程序 getUserProfile:fail must be invoked by user tap gesture,在实现点击头像需要出发抖音小程序获取用户原生头像的操作中,无论如何也无法触发抖音的原生窗口! 问题描述 这个问题我找了很多博主的方法ÿ…...
(undone) MIT6.S081 2023 学习笔记 (Day5: LAB4 traps)
LAB 网页:https://pdos.csail.mit.edu/6.S081/2023/labs/traps.html 任务1:RISC-V assembly (完成) 初步看问题要求,这是一道文科题(问答题) 在你的 xv6 仓库中有一个文件 user/call.c。执行 make fs.img 会对其进行编译,并生成…...
前端笔记----
在我的理解里边一切做页面的代码都是属于前端代码。 之前用过qt框架,也是用来写界面的,但是那是用来写客户端的,而html是用来写web浏览器的,相较之下htmlcssJavaScript写出来的界面是更加漂亮的。这里就记录我自个学习后的一些笔…...
学习华为熵减,激发组织活力
目录 为什么学习华为? 学习华为什么? 一、势:顺势而为,在风口上猪都会飞起来。 二、道:就是认识和利用规律层面,文化和制度创新就是企业经营之道。 三、法:就是一套价值管理的变革方法论。…...
9Hive数据倾斜
这里写目录标题 数据倾斜问题剖析数据倾斜解决方案1. 空值引发的数据倾斜2. 不同数据类型引发的数据倾斜3. 不可拆分大文件引发的数据倾斜4. 数据膨胀引发的数据倾斜5. 表连接时引发的数据倾斜6. 确实无法减少数据量引发的数据倾斜 总结 数据倾斜问题剖析 数据倾斜是分布式系统…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
