014 - STM32学习笔记 - I2C访问存储器(一)

news2024/11/22 19:00:31

014 - STM32学习笔记 - I2C访问存储器

1、存储器分类

存储器主要分为两类:易失性存储器和非易失性存储器,从字面上理解,判断易失/非易失主要取决于设备掉电后,存储的数据是否会丢失。常规的来说,易失性存储器存取速度快,掉电后数据丢失,非易失性存储器掉电数据不丢失,但读取速度相对于易失性存储器来说较慢。

易失性存储器中常见的为RAM存储器,即随机存储器(Random Access Memory),随机存储是指当存储器的消息倍读取或者写入时,需要的时间和这段信息所在位置无关,,根据RAM的读取机制,又分为动态随机存储器DRAM(Dynamic RAM)和静态随机存储器SRAM(Static RAM)两种。

2、I2C读写EEPROM

I2C协议简介

I2C协议(Inter-Integrated Circuit)时飞利浦公司开发的,由于它引脚少,硬件实现简答,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,所以被广泛的应用在系统内多个集成电路(IC)之间的通讯。

在这里插入图片描述

I2C物理层

I2C是支持支持多设备通信的总线,所谓“总线”,是指多个设备共用信号线,在一个I2C通讯总线中,可以连接多个I2C通讯设备,支持多个主机于从机通讯,所有连接在I2C总线中的设备,都有一个独立的地址,主机可以利用这个地址访问不同的设备,I2C有两条总线,SCL(双向串行数据)总线和SDA(川航时钟)总线,SDA用来表示数据,SCL为数据收发提供同步时钟信号。

总线通过上拉电阻,当I2C设备空闲时,会输出高阻态,当所有设备都空闲时,由上拉电阻把总线拉成高电平,当多个主机同时使用总线时,为了防止数据通途,会利用仲裁的方式决定由哪个设备占用总线。

这里解释一下,高阻态再电路中的电平表现形式为非高非低,假设上图的EEPROM和ADC都不输出数据,那么EEPROM和ADC都处于高阻态,那么当前SDA总线就处于高电平状态,如果此时EEPROM输出数据为0,那么再EEPROM的SDA端就相当于输出低电平,此时SDA总线就处于低电平状态。

I2C具有是那种传输模式,标准模式(100kbit/s)、快速模式(400kbit/s)和高速模式(3.4Mbit/s),目前多数I2C设备不支持高速模式。

关于I2C的架构和通讯过程,内容太多,篇幅很长,这里不做赘述了,有兴趣的可以看看相关资料。

下面开始实战编程:

结合之前USART的内容,首先对I2C的GPIO引脚进行配置,配置之前,对相关的参数进行宏定义:

#define EEPROM_ADDR             0xA0					//EEPROM地址

#define EEPROM_I2C              I2C1					//选择I2C1
#define EEPROM_I2C_CLK          RCC_APB1Periph_I2C1		 //I2C1总线时钟
#define EEPROM_I2C_SPEED        400000					//I2C速率
#define EEPROM_I2C_OAdr         0x77					//本机I2C地址

#define EEPROM_SCL_GPIO_PORT    GPIOB					//SCL端口
#define EEPROM_SCL_GPIO_CLK     RCC_AHB1Periph_GPIOB	 //SCL时钟
#define EEPROM_SCL_PIN          GPIO_Pin_6				//SCL引脚
#define EEPROM_SCL_AF           GPIO_AF_I2C1			//I2C复用功能
#define EEPROM_SCL_PinSoruce    GPIO_PinSource6			//PB6源

#define EEPROM_SDA_GPIO_PORT    GPIOB					//SDA端口
#define EEPROM_SDA_GPIO_CLK     RCC_AHB1Periph_GPIOB	 //SDA时钟
#define EEPROM_SDA_PIN          GPIO_Pin_7				//SDA引脚
#define EEPROM_SDA_AF           GPIO_AF_I2C1			//I2C复用功能
#define EEPROM_SDA_PinSoruce    GPIO_PinSource7			//PB7源

接下来对GPIO进行配置

void EEPROM_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //使能GPIO时钟,只要是外设,第一步一定是开时钟
    RCC_AHB1PeriphClockCmd(EEPROM_SCL_GPIO_CLK|EEPROM_SDA_GPIO_CLK,ENABLE);
    //选择开漏输出
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    //选择悬空
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    //速度设置为50MHz,这里I2C的速度最大为400KHz,只要速度不小于这个就行
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //将PB6复用功能连接到I2C1,用法与USART的相同
    GPIO_PinAFConfig(EEPROM_SCL_GPIO_PORT,EEPROM_SCL_PinSoruce,EEPROM_SCL_AF);
    //将PB7复用功能连接到I2C1
    GPIO_PinAFConfig(EEPROM_SDA_GPIO_PORT,EEPROM_SDA_PinSoruce,EEPROM_SDA_AF);
    //选择模式为复用模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    //设置SCL的引脚号
    GPIO_InitStructure.GPIO_Pin = EEPROM_SCL_PIN;
    //初始化SCL引脚
    GPIO_Init(EEPROM_SCL_GPIO_PORT,&GPIO_InitStructure);
    //设置SDA的引脚号
    GPIO_InitStructure.GPIO_Pin = EEPROM_SDA_PIN;
    //初始化SDA引脚
    GPIO_Init(EEPROM_SDA_GPIO_PORT,&GPIO_InitStructure);
}

GPIO配置完后,就该对I2C进行配置了

//初始化I2C模式
void EEPROM_I2C_ModeConfig(void)
{
    I2C_InitTypeDef I2C_InitStructure;
    //使能I2C时钟,只要是外设,第一步一定是开时钟
    RCC_APB1PeriphClockCmd(EEPROM_I2C_CLK,ENABLE);
    //设置I2C响应使能
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    //设置地址为7位
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    //设置I2C时钟速率为400KHz
    I2C_InitStructure.I2C_ClockSpeed = EEPROM_I2C_SPEED;
    //设置I2C占空比为Low:High = 2
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    //设置I2C模式为I2C_Mode_I2C模式
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    //设置I2C本机地址为0x77(只要和总线上其他设备地址不冲突即可)
    I2C_InitStructure.I2C_OwnAddress1 = EEPROM_I2C_OAdr;
    //初始化I2C
    I2C_Init(EEPROM_I2C,&I2C_InitStructure);
    //使能I2C
    I2C_Cmd(EEPROM_I2C,ENABLE);
}

以上就是对GPIO及I2C的配置,这里仅仅是进行配置,对于I2C总线的读写功能需要单独实现,结合I2C的时序图,具体实现如下:

在这里插入图片描述

在时序图中,关于EVx的说明,在stm32f4xx_i2c.c文件中有说明,这里贴出来看一下

@param  I2C_EVENT: specifies the event to be checked. 
  *          This parameter can be one of the following values:
  *            @arg I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: EV1
  *            @arg I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: EV1
  *            @arg I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED: EV1
  *            @arg I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED: EV1
  *            @arg I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED: EV1
  *            @arg I2C_EVENT_SLAVE_BYTE_RECEIVED: EV2
  *            @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF): EV2
  *            @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL): EV2
  *            @arg I2C_EVENT_SLAVE_BYTE_TRANSMITTED: EV3
  *            @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF): EV3
  *            @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL): EV3
  *            @arg I2C_EVENT_SLAVE_ACK_FAILURE: EV3_2
  *            @arg I2C_EVENT_SLAVE_STOP_DETECTED: EV4
  *            @arg I2C_EVENT_MASTER_MODE_SELECT: EV5
  *            @arg I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: EV6     
  *            @arg I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: EV6
  *            @arg I2C_EVENT_MASTER_BYTE_RECEIVED: EV7
  *            @arg I2C_EVENT_MASTER_BYTE_TRANSMITTING: EV8
  *            @arg I2C_EVENT_MASTER_BYTE_TRANSMITTED: EV8_2
  *            @arg I2C_EVENT_MASTER_MODE_ADDRESS10: EV9

根据时序图,先实现主发送器的写函数,程序如下(关于超时检测的程序会放在最后,前面看不懂的,可以先忽略超时检测的内容):

//byte write函数
uint32_t EEPROM_Byte_Write(uint8_t *pData,uint8_t addr)
{
    I2CTimeout = I2CT_FLAG_TIMEOUT;															 /* 设置超时等待时间 */
    while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY))   									   /* 检测I2C总线状态 */
    {
        if((I2CTimeout--) == 0) 
            return I2C_TIMEOUT_UserCallback(0);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*-----------------------1 产生开始信号 ----------------------------*/
    I2C_GenerateSTART(EEPROM_I2C,ENABLE); 
    /*-----------------------2 等待EV5事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(1);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*-----------------------3 发送要访问的设备地址 ----------------------------*/
    I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
    /*-----------------------4 等待EV6事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(2);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*------5 发送要写入的EEPROM内部地址,即EEPROM内部存储器地址 -----*/
    I2C_SendData(EEPROM_I2C,addr);
    /*-----------------------6 等待EV8事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(3);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*-----------------------7 发送数据 ----------------------------*/
    I2C_SendData(EEPROM_I2C,*pData);
    /*-----------------------8 等待EV8事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(4);
    }
    /*-----------------------9 发送停止信号 ----------------------------*/
    I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
    printf("\r\nEEPROM数据写入完成!写入数据为:0x%x\r\n",*pData);
    return 1;
}

在实现了写数据到EEPROM中后,还需要再实验一个从EEPROM中读取数据的函数,用来验证我们上面的写程序,同样,读取的函数也要根据时序图来编写

在这里插入图片描述

读数据实现:

uint8_t readTemp = 0;
    I2CTimeout = I2CT_FLAG_TIMEOUT;															 /* 设置超时等待时间 */
    while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY))   									   /* 检测I2C总线状态 */
    {
        if((I2CTimeout--) == 0) 
            return I2C_TIMEOUT_UserCallback(5);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*-----------------------1 产生开始信号 ----------------------------*/
    I2C_GenerateSTART(EEPROM_I2C,ENABLE); 
    /*-----------------------2 等待EV5事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(6);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*-----------------------3 发送要访问的设备地址 ----------------------------*/
    I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
    /*-----------------------4 等待EV6事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(7);
    }
    
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    /*------5 发送要写入的EEPROM内部地址,即EEPROM内部存储器地址 -----*/
    I2C_SendData(EEPROM_I2C,addr);
    /*-----------------------6 等待EV8事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(8);
    }
    
    /****************************************************************************************/
    I2CTimeout = I2CT_FLAG_TIMEOUT;															 /* 设置超时等待时间 */
    /*-----------------------7 产生第二次开始信号 ----------------------------*/
     I2C_GenerateSTART(EEPROM_I2C,ENABLE); 
    /*-----------------------8 等待EV5事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(9);
    }
    /*----------------------- 发送要访问的设备地址:发送read方向 ----------------------------*/
    I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);
    /*-----------------------9 等待EV6事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(10);
    }
    I2CTimeout = I2CT_FLAG_TIMEOUT;															/* 设置超时等待时间 */
    I2C_AcknowledgeConfig(EEPROM_I2C,DISABLE);												 /* 关闭响应 */
    /*-----------------------11 等待EV7事件 ----------------------------*/
    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS)
    {
        if((I2CTimeout--) == 0)
            return I2C_TIMEOUT_UserCallback(11);
    }
    /*-----------------------10 读取数据 ----------------------------*/
    readTemp = I2C_ReceiveData(EEPROM_I2C);
    /*-----------------------12 发送停止信号 ----------------------------*/
    I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
    printf("\r\nEEPROM数据读取完成!\r\n");
    I2C_AcknowledgeConfig(EEPROM_I2C,ENABLE);                                                  /* 使能响应,方便下一次操作 */	
    return readTemp;

下来说明一下超时检测,当主控发送信号后,需要等待从机反馈响应事件,可以使用I2C_CheckEvent来检测对应的事件信号,但是这里需要主义的是,当发主机发送数据给从机后,从机并不能在第一时间就反馈响应,可能需要等一会,那我们不可能就判断一次,而且若从机一直未响应,也不可能一直在这里等待响应信号,因此我们设置一个超时检测变量I2CTimeout,当响应信号一直未收到时,就在while循环里面一直给I2CTimeout进行自减操作,直到I2CTimeout自减到0为止还没有收到响应信号的话,就认为等待响应超时,那么就可以直接退出了。

当产生响应超时时,可以通过回调函数I2C_TIMEOUT_UserCallback来提示用户I2C响应超时,具体实现如下:

static  uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* EEPROM_ERROR为宏实现,实际为printf */
  /* #define EEPROM_ERROR(fmt,arg...)    printf("<<-EEPROM-ERROR->> "fmt"\n",##arg) */
  EEPROM_ERROR("I2C 等待超时!errorCode = %d",errorCode);
  return 0;
}

完成以上内容后,就可以在主函数中调用来测试IIC读写EEPROM的功能了,main.c的实现如下:

#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_systick.h"
#include "bsp_usart_dma.h"				/* 这里用的都是之前学习过程中自己写的板级支持包 */
#include "stm32f4xx_dma.h"
#include "bsp_i2c_ee.h"
#include <stdio.h>

int main(void)
{
    int8_t Test_Addr = 0x00;
    int8_t Test_WriteByte = 0x47;
    int8_t Test_ReadByte = 0;
    LED_Config();
    DEBUG_USART1_Config();
    SysTick_Init();
    printf("这是一个EEPROM测试实验\n");
    printf("\r\n初始化EEPROM\r\n");
    EEPROM_GPIO_Config();
    printf("\r\n初始化I2C模式配置\r\n");
    EEPROM_I2C_ModeConfig();
    EEPROM_Byte_Write(&Test_WriteByte,Test_Addr);
    Delay_ms(10);
    Test_ReadByte = EEPROM_Byte_Read(Test_Addr);
    printf("I2C中读取到的数据为:0x%x\n",Test_ReadByte);
    while(1)
    {
        if(Test_ReadByte == Test_WriteByte)
        {
            LED_G_TOGGLE;
            Delay_ms(1000);
        }
        else
        {
            LED_R_TOGGLE;
            Delay_ms(1000);
        }
    }
}

这里需要注意的是,我在刚写完程序的时候,在Test_ReadByte = EEPROM_Byte_Read(Test_Addr);之前没有加延时函数,在测试过程中,一直卡在读取的第7步过不去:

<<-EEPROM-ERROR->> I2C 等待超时!errorCode = 7

查了一下资料,才知道STM32在向EEPROM写入数据后,如果立马就去读数据,但是这时EEPROM内部正在处理自己的事情(可能正在写数据),因此立马去读的话,就没办法往下继续运行了。因此在这里增加一个延时函数,确保EEPROM能完成内部逻辑。
最终验证结果:
在这里插入图片描述

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

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

相关文章

Django基础入门⑥:Django过滤器和标签讲解

Django基础入门⑥&#xff1a;Django过滤器和标签讲解 Django过滤器过滤器语法过滤器应用获取变量的长度截取指定个数的词返回指定键的排序列表add给变量值加“n” Django url标签url标签动态url Django自定义标签如何自定义标签定义之前的准备工作模块变量register自定义标签赋…

Java 对接google WIFI定位API

1.创建Http请求工具类 1.1.引入httpclient <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.10</version></dependency> 1.2.封装Http工具类 /*** Http请求* a…

MySQL 高级语句 一

目录 一、MySQL高级&#xff08;进阶&#xff09;SQL语句1. select2. distinct3. where4. and or5. in6. between7. 通配符8. order by9. 函数9.1 数学函数9.2 聚合函数9.3 字符串函数 二、高级查询语句2.1 group by &#xff08;用于分组和汇总&#xff09;2.2 having2.3 别名…

如何在 XMind 中绘制流程图

XMind 是专业强大的思维导图软件,由于其结构没有任何限制,很多朋友特别喜欢用它来绘制流程图。禁不住大家的多次询问,今天 XMind 酱就将这简单的流程图绘图方法分享给大家。 在 XMind 中,绘制流程图的主角是「自由主题」和「联系」。它们可以打破思维导图的限制,让你自由…

《异常检测——从经典算法到深度学习》21 Anomaly Transformer:具有关联差异的时间序列异常检测

We # 《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Do…

[NX亲测有效]Ubuntu,Jetson nano,NX板开机设置开机自起,Jetson nano,NX设置x11vnc开机自起

&#xff01;&#xff01;Ubuntu,Jetson nano,NX板开机设置开机自起&#xff0c;nano NX设置x11vnc开机自起&#xff01;&#xff01; 1.创建一个rc-local自启服务 2.创建运行脚本 3.启动服务 4.NX&#xff0c;nano设置x11vnc并设置开机自启 大功告成&#xff01;编写不易…

【中级软考】软件设计-考试介绍

一、软考好处 通过软考认证可以抵扣当年的 3600 元的个税,并且有些城市可以积分落户,同时获得证书可以获得同等级别的职称。计算机方向的职称是以考代评,所以获得中级软考证书就相当于获得同等的中级计算机工程师职称,获得高级软考证书就相当于获得同等的高级计算机工程师…

如何使用@umijs/plugin-qiankun搭建微前端项目

umijs/plugin-qiankun是一个基于UmiJS框架的插件&#xff0c;用于实现乾坤微前端架构。乾坤微前端是一种前端架构模式&#xff0c;可以将一个大型的前端应用拆分成多个小型的子应用&#xff0c;每个子应用可以独立开发、独立部署、独立运行&#xff0c;同时可以通过乾坤框架进行…

ArduPilot开源代码之AP_InertialSensor

ArduPilot开源代码之AP_InertialSensor 1. 源由2. AP_InertialSensor类2.1 init2.2 periodic2.3 update 3. 重要应用方法3.1 BatchSampler::push_data_to_log3.2 wait_for_sample3.2 calibrate_gyros 4. 总结5. 参考资料 1. 源由 前面研读了IMU如何通过front-end/back-end获取…

基于SpringBoot+kaptcha的验证码生成

教程 1.添加 Kaptcha 依赖 在 pom.xml 文件中添加 Kaptcha 依赖&#xff1a; <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency> <!--或者 都…

【深度学习 | 机器学习】干货满满 | 近万字总结了 12 个令人惊艳的神经网络可视化工具!

文章目录 一、神经网络可视化难点在哪里&#xff1f;二、神经网络可视化方法三、神经网络可视化解释的工具3.1 draw_convnet3.2 NNSVG3.3 PlotNeuralNet3.4 Tensorboard3.5 Caffe3.6 Matlab3.7 Keras.js3.8 DotNet3.9 Graphviz3.10 ConX3.11 ENNUI3.12 Neataptic 神经网络可视化…

linux下Python的学习(五)用matplotlib画iostat的折线图

之前写测试脚本的时候习惯用shell来写&#xff0c;只不过用AWK(个人觉得awk是shell的精髓)处理表格的时候比Python复杂的多&#xff0c;因为Python有很多现成的库&#xff0c;直接调用就可以。下面用Python自带的matplotlib函数实现一下对iostat log的采样 比如有一个记录iosta…

第一章 数据可视化简介(复习)

第一章 数据可视化简介 什么是可视化 定义&#xff1a;通过可视表达增强人们完成某些 任务的效率 The American Heritage Dictionary&#xff1a; The act or process of interpreting in visual terms or of putting into visible form&#xff08;用可视形式进行解释的 动作…

做性能测试必须掌握的基本概念和套路

目录 性能优化的常见概念 性能调优的思路 1.性能摸底测试 2.定义性能优化的目标 3.分析 针对内存&#xff1a; OOM&#xff1a; 针对IO&#xff1a; 文件IO&#xff1a; 总结&#xff1a; 经常听到人说&#xff0c;做个性能优化&#xff0c;吞吐量越高越好&#xff1…

2023 年开发者必须知道的 6 个 AI 工具

自Chat GPT发布以来&#xff0c;AI在各个领域都出现了令人惊艳的产品&#xff0c;在编程方面也是如此。这些由 AI 驱动的工具使用算法快速准确地生成代码&#xff0c;从而节省程序员的时间和精力。虽然目前AI写出来的代码还不能完全替代人类&#xff0c;但开发人员完全可以作为…

安卓开发之广播接收器

搞安全的&#xff0c;用到哪学到哪 广播的几个部分 1.发送广播的逻辑&#xff08;需要先定义Intent方法&#xff0c;再进行send&#xff09; 2.接收广播的逻辑&#xff08;继承BroadcastReceiver方法&#xff09; 3.开关控制广播&#xff0c;也就是注册广播的过程&#xff…

Express框架与Mongodb的结合使用

前言 如果你打开这篇文章&#xff0c;说明已经开始有做项目的打算了。 这里有express和mongodb的相关参考教程&#xff0c;遇到问题可以在里面找到答案&#xff1a; Express框架从入门到如土 一文入门Mongodb 这里说下为什么要express框架和mongodb结合。express框架不是指单…

【MySQL数据库】MySQL 高级SQL 语句

[TOC](MySQL 高级SQL 语句 一、MySQL 高级SQL 语句1.1select -显示表格中一个或数个字段的所有数据记录1.2distinct不显示重复的数据记录1.3where有条件查询1.4and、or且 或1.5in 显示已知的值的数据记录1.6between 显示两个值范围内的数据记录1.7通配符&#xff0c;通常通配符…

【图神经网络】5分钟快速了解Open Graph Benchmark

10分钟快速了解Open Graph Benchmark Open Graph Benchmark (OGB)安装OGB简单使用节点分类任务数据集链路预测任务数据集图属性预测任务数据集Large-Scale Graph ML Datasets 内容来源 Open Graph Benchmark (OGB) Open Graph Benchmark&#xff08;OGB&#xff09;是用于图机…

QT学习资料整理

5、QMainWindow QMainWindow是一个为用户提供主窗口程序的类&#xff0c;包含一个菜单栏&#xff08;menu bar&#xff09;、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget)&#xff0c;是许多应用程序的基础&…