STM32实战之深入理解I²C通信协议

目录

I²C的物理层

I²C的协议层

I²C特点

I²C 总线时序图

软件模拟I²C时序分享

例程简介

例程分享

STM32的I²C外设


IIC(Inter-Integrated Circuit),也称为I²C或TWI(Two-Wire Interface),是一种广泛使用的串行总线接口,用于连接低速度的集成电路。这种通信协议非常适合在单个主设备和多个从设备之间进行短距离通信。

I²C的物理层

IIC通信只需要两根线:一个是串行数据线(SDA),另一个是串行时钟线(SCL)。这两根线都需要通过上拉电阻连接到正电源,以确保在没有信号驱动时,线路能够保持在高电平状态。

I²C的协议层

IIC协议定义了一系列的信号,包括开始信号、停止信号、数据有效性和应答信号。开始信号和停止信号用于标识一次通信的开始和结束,而数据有效性确保数据在时钟信号稳定时被读取。应答信号则是从设备对接收数据的确认。

I²C特点

  1. 两线制接口:I2C通信只需要两根线,一根是串行数据线(SDA),另一根是串行时钟线(SCL),所以I2C为半双工通信。
  2. 多主设备:I2C允许多个主设备(master)和多个从设备(slave)在同一总线上通信。
  3. 地址识别:每个从设备都有一个唯一的地址,主设备通过这个地址与特定的从设备通信。
  4. 同步通信:I2C是一种同步通信协议,数据传输是由时钟信号(SCL)来同步的。
  5. 支持多速率:I2C支持多种不同的数据传输速率,包括标准模式(100kbps)、快速模式(400kbps)、快速模式加(1Mbps)和高速模式(3.4Mbps)。
  6. 软件可配置:I2C设备的地址和一些功能可以通过软件进行配置。
  7. 简单易用:I2C接口的硬件实现相对简单,易于集成到各种微控制器和其他集成电路中。
  8. 应用广泛:I2C广泛应用于各种电子产品中,如手机、电视、医疗设备和嵌入式系统等。
  9. 支持热插拔:I2C设备支持在系统运行时添加或移除,即热插拔。
  10. 总线仲裁:在多主设备的情况下,I2C协议提供了一种仲裁机制,以决定哪个主设备可以控制总线。
  11. 时钟拉伸:从设备可以通过拉低时钟线来暂停通信(称为时钟拉伸),以便有足够的时间处理接收到的数据或完成数据发送。
  12. 应答机制:I2C通信中包含应答(ACK)和非应答(NACK)信号,用于指示数据是否成功接收。

I2C由于其简单和灵活的特性,成为了连接低速外围设备,如传感器、EEPROM、显示器等的理想选择。

I²C 总线时序图

总线时序图是理解IIC通信的关键。它展示了开始信号、数据位的传输、应答位以及停止信号的顺序。在IIC通信中,数据位在SCL线为高电平时被认为是稳定的,因此数据应该在SCL的高电平期间被读取。

起始条件: SCL高电平期间,SDA从高电平切换到低电平

终止条件: SCL高电平期间,SDA从低电平切换到高电平

起始和终止条件都是由主机产生

发送一个字节: SCL低电平期间,主机将数据位依次放到SDA线上,(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许由数据变化,依次循环上述过程8次即可发送一个字节

接收一个字节: SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所哟一SCL高电平期间SDA不允许有数据变换,依次循环上述过程8次,即可接收一个字节(主机在接收数据前需要先释放SDA)

发送应答:  主机在接收完一个字节后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答

接收应答:  主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前需要释放SDA)

软件模拟I²C时序分享

/**
  * @brief  定义SCL写函数
  * @param  None
  * @retval None
  */
    void myi2c_w_scl(uint8_t bitval){
        GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)bitval); //将bitval的值写入GPIOA的Pin_1,也就是SCL线
        Delay_us(10); //延迟10微秒
    }
    
    /**
  * @brief  定义SDA写函数
  * @param  None
  * @retval None
  */
    void myi2c_w_sda(uint8_t bitval){
        GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)bitval); //将bitval的值写入GPIOA的Pin_0,也就是SDA线
        Delay_us(10); //延迟10微秒
    }
    
    /**
    * @brief  读取SDA数据
    * @param  None
    * @retval None
    */
    uint8_t myi2c_r_sda(void){
        return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); //读取GPIOA的Pin_0,也就是SDA线的值
    }

/**
  * @brief  软件模拟I2C初始化
    *        SDA        PA0        推挽输出
    *        SCL        PA1        推挽输出
  * @param  None
  * @retval None
  */
void myi2c_init(void){
    //初始化GPIO口
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
      GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //设置GPIO模式为开漏输出
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //设置GPIO的Pin_0和Pin_1
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO速度为50MHz
      GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
    
    //释放总线
    GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1); //将GPIOA的Pin_0和Pin_1设置为高电平,释放总线
}

/**
  * @brief  I2C起始条件
  * @param  None
  * @retval None
  */
void i2c_start(void){
    //输出起始条件
    myi2c_w_sda(1); //将SDA线设置为高电平
    myi2c_w_scl(1); //将SCL线设置为高电平
    
    myi2c_w_sda(0); //将SDA线设置为低电平,生成起始条件
    myi2c_w_scl(0); //将SCL线设置为低电平
}

/**
  * @brief  I2C结束条件
  * @param  None
  * @retval None
  */
void i2c_stop(void){
    //输出起始条件
    myi2c_w_sda(0); //将SDA线设置为低电平
    myi2c_w_scl(1); //将SCL线设置为高电平
    myi2c_w_sda(1); //将SDA线设置为高电平,生成结束条件
}

/**
* @brief  I2C发送一个字节
  * @param  None
  * @retval None
  */
void myi2c_sendbyte(uint8_t byte){
    for(uint8_t i = 0; i < 8; i++){ //循环8次,发送一个字节
        myi2c_w_sda(byte & 0x80 >> i);    //每发送一次向右偏移一个字节
        myi2c_w_scl(1); //将SCL线设置为高电平
        myi2c_w_scl(0); //将SCL线设置为低电平
    }
}

/**
  * @brief  I2C接收一个字节
  * @param  None
  * @retval None
  */
uint8_t myi2c_recv_byte(void){
    uint8_t byte = 0; //定义一个字节变量
    for(uint8_t i = 0; i < 8; i++){ //循环8次,接收一个字节
        myi2c_w_scl(1); //将SCL线设置为高电平
        if(myi2c_r_sda() == 1){byte |= (0x80 >> i);} //如果SDA线为高电平,将byte的相应位设置为1
            myi2c_w_scl(0); //将SCL线设置为低电平
    }
    return byte; //返回接收到的字节
}

/**
  * @brief  I2C接收应答
  * @param  None
  * @retval None
  */
uint8_t myi2c_recv_ack(void){
    uint8_t ackbit = 0; //定义一个应答位变量
    myi2c_w_sda(1); //将SDA线设置为高电平
    myi2c_w_scl(1); //将SCL线设置为高电平
    ackbit = myi2c_r_sda(); //读取SDA线的值,也就是应答位
    myi2c_w_scl(0); //将SCL线设置为低电平
    return ackbit; //返回应答位
}

/**
* @brief  I2C发送应答
  * @param  None
  * @retval None
  */
void myi2c_send_ack(uint8_t ackbit){
    myi2c_w_sda(ackbit); //将应答位的值写入SDA线
    myi2c_w_scl(1); //将SCL线设置为高电平
    myi2c_w_scl(0); //将SCL线设置为低电平
}

软件模拟IIC驱动AT24C02分享

例程简介

通过I2C协议与AT24C04 EEPROM芯片进行交互的函数。EEPROM代表电可擦除可编程只读存储器,这是一种非易失性存储器,用于计算机和其他电子设备中存储断电后必须保存的少量数据。

以下是每个函数的简要概述:

  1. ​AT24_init​​:此函数初始化与AT24C04芯片通信的I2C接口。
  2. ​AT24_write_byte​​:此函数将单个字节的数据写入AT24C04芯片的指定地址。
  3. ​AT24_read_byte​​:此函数从AT24C04芯片的指定地址读取单个字节的数据。
  4. ​AT24_write_page​​:此函数将多个字节的数据写入AT24C04芯片的指定地址。AT24C04的内存被划分为多个页面,每个页面可以容纳多个字节的数据。
  5. ​AT24_WriteBuffer​​:此函数将数据缓冲区写入AT24C04芯片。它考虑到芯片内存的页面结构,并在必要时跨多个页面写入数据。
  6. ​AT24_readBuffer​​​:此函数从AT24C04芯片读取数据缓冲区。与​​AT24_WriteBuffer​​一样,它也考虑到芯片内存的页面结构。

例程分享

/*源代码*/
#include "AT24.h"

uint8_t AT24_ADDR_W1	= 0XA0;
uint8_t AT24_ADDR_W2	= 0XA2;
uint8_t AT24_ADDR_R1	= 0xA1;
uint8_t AT24_ADDR_R2	= 0xA3;


/**
  * @brief  AT24C04初始化
  * @param  None
  * @retval None
  */
void AT24_init(void){
	
	myi2c_init();
	
}
	
/**
  * @brief  指定地址写入一个字节数据(0 ---- 255)
  * @param  uint16_t addr	写入数据地址
  * @param	uint8_t data	写入字节
  * @retval 写入成功返回4
  */
uint8_t AT24_write_byte(uint16_t addr, uint8_t data){
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_W1);	//发送从机地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24寻址未应答\r\n");
		return 1;
	}
	
	myi2c_sendbyte(addr);	//发送要写入的地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24内部寻址未应答\r\n");
		return 2;
	}
	
	myi2c_sendbyte(data);	//发送要写入的数据
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24写入数据未应答\r\n");
		return 3;
	}
	i2c_stop();		//发送停止位
	printf("AT24写入数据成功\r\n");
	return  4;
}


/**
  * @brief  指定地址读出一个字节数据(0 ---- 255)
  * @param  uint16_t addr	读数据地址
  * @retval 成功返回读出数据
  */

uint8_t AT24_read_byte(uint16_t addr){
	uint8_t read_data = 0;
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_W1);	//发送从机地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24寻址未应答\r\n");
		return 1;
	}
	
	myi2c_sendbyte(addr);	//发送要写入的地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24内部寻址未应答\r\n");
		return 2;
	}
	i2c_stop();		//发送停止位
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_R1);	//发送从机地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24寻址未应答\r\n");
		return 1;
	}
	read_data = myi2c_recv_byte();
	myi2c_send_ack(1);
	i2c_stop();		//发送停止位
	return read_data;
}


/**
  * @brief  指定地址页写入数据(0 ---- 255)
  * @param  uint16_t addr	写入数据地址
  * @param	uint8_t data	写入字节首地址
  * @param	uint8_t num 写入字节个数
  * @retval 写入成功返回4
  */
uint8_t AT24_write_page(uint16_t addr, uint8_t num, uint8_t *data){
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_W1);	//发送从机地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24寻址未应答\r\n");
		return 1;
	}
	
	myi2c_sendbyte(addr);	//发送要写入的地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24内部寻址未应答\r\n");
		return 2;
	}
	while(num--){
		myi2c_sendbyte(*data);	//发送要写入的数据
		if(myi2c_recv_ack() == 1){
			i2c_stop();		//发送停止位
			printf("AT24写入数据未应答\r\n");
			return 3;
		}
		data++;
	}
	
	i2c_stop();		//发送停止位
	printf("AT24写入数据成功\r\n");
	return  4;
}


/**
  * @brief  随机写
  * @param  uint8_t *pBuffer	写入数据的首地址
  * @param  uint32_t WriteAddr	写入地址
  * @param  uint16_t NumByteToWrite	数据长度
  * @retval None
  */
void AT24_WriteBuffer(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite){
	uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
	Addr = WriteAddr % 16;	//判断地址是否为整页
	count = 16 - Addr;			//当前页剩余字节数
	NumOfPage =  NumByteToWrite / 16;	//需要的整页数
	NumOfSingle = NumByteToWrite % 16;	//除整页剩余的字节数
	
	if (Addr == 0) /*整页开始  */
  {
    if (NumOfPage == 0) /*所写数据不够一整页,直接调用页编程函数 */
    {
      AT24_write_page(WriteAddr, NumByteToWrite, pBuffer);
    }
    else /*所写数据超过一页*/
    {
      while (NumOfPage--)	//整页写
      {
        AT24_write_page(WriteAddr, 16, pBuffer);
        WriteAddr +=  16;
        pBuffer += 16;
      }

      AT24_write_page(WriteAddr, NumOfSingle, pBuffer);	//除整页之外剩余的
    }
  }
  else /*不是整页开始写  */
  {
    if (NumOfPage == 0) /*所写不到一页 */
    {
      if (NumOfSingle > count) /*所需空间大于当前页所剩空间*/
      {
        temp = NumOfSingle - count;	//当前页写完之后剩余量

        AT24_write_page(WriteAddr, count, pBuffer);	//在当前页写,写满
        WriteAddr +=  count;
        pBuffer += count;

        AT24_write_page(WriteAddr, temp, pBuffer);	//剩余写入下一页
      }
      else
      {
        AT24_write_page(WriteAddr, NumByteToWrite, pBuffer);	//直接写当前页
      }
    }
    else /*写入数据量大于一页 */
    {
      NumByteToWrite -= count;	//写满当前页所剩数据
      NumOfPage =  NumByteToWrite / 16;	//要写入的整页
      NumOfSingle = NumByteToWrite % 16;	//写完整页剩余的字节

      AT24_write_page(WriteAddr, count, pBuffer);//把当前页写满
      WriteAddr +=  count;
      pBuffer += count;

      while (NumOfPage--)	//写整页
      {
        AT24_write_page(WriteAddr, 16, pBuffer);
        WriteAddr +=  16;
        pBuffer += 16;
      }

      if (NumOfSingle != 0)	//写剩余不满一页的字节
      {
        AT24_write_page(WriteAddr, NumOfSingle, pBuffer);
      }
    }
  }
}

/**
  * @brief  随便读
  * @param  None
  * @retval None
  */
uint8_t AT24_readBuffer(uint16_t addr, uint16_t num, uint8_t *recvdata){
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_W1);	//发送从机地址
		Delay_us(10);
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24器件寻址未应答\r\n");
		return 1;
	}

	myi2c_sendbyte(addr);	//发送要写入的地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24内部寻址未应答\r\n");
		return 2;
	}
	i2c_stop();		//发送停止位
	i2c_start();	//发送起始信号
	myi2c_sendbyte(AT24_ADDR_R1);	//发送从机地址
	if(myi2c_recv_ack() == 1){
		i2c_stop();		//发送停止位
		printf("AT24器件2寻址未应答\r\n");
		return 1;
	}
	while(num--){
		*recvdata = myi2c_recv_byte();
		myi2c_send_ack(0);
		recvdata++;
		Delay_us(5);
	}
	myi2c_send_ack(1);
	i2c_stop();		//发送停止位
	return num;
}
/*头文件*/
#ifndef __AT24_H_
#define __AT24_H_

#include "stm32f4xx.h"                  // Device header
#include "myi2c.h"
#include "usart.h"
#include "delay.h"

void AT24_init(void);
uint8_t AT24_write_byte(uint16_t addr, uint8_t data);
uint8_t AT24_read_byte(uint16_t addr);
uint8_t AT24_write_page(uint16_t addr, uint8_t num, uint8_t *data);
void AT24_WriteBuffer(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
uint8_t AT24_readBuffer(uint16_t addr, uint16_t num, uint8_t *recvdata);
#endif

STM32的I²C外设

STM32内部集成了硬件I²C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据发送等功能,减轻CPU的负担。STM32的I²C外设支持多主机模式、7位或10位地址模式、不同的通信速度(标准速度高达100KHZ,快速400KHZ)、DMA,以及兼容SMBus协议。

  1. 硬件自动执行:STM32内部的硬件I2C模块可以自动执行时钟生成、起始终止条件生成、应答位收发、数据发送等功能,减轻了CPU的负担,使通信更高效。
  2. 多主机模式:STM32的硬件I2C模块支持多主机模式,可以实现多个主机设备在同一总线上进行通信。
  3. 7位或10位地址模式:STM32的硬件I2C模块支持7位或10位地址模式,可以适应不同设备的寻址需求。
  4. 不同通信速度:STM32的硬件I2C模块支持不同的通信速度,标准速度可达100KHz,快速模式可达400KHz,可以根据具体需求选择合适的通信速率。
  5. 支持DMA:STM32的硬件I2C模块支持DMA(直接内存访问)功能,可以通过DMA传输数据,提高数据传输效率,减少CPU的负载。
  6. 兼容SMBus协议:STM32的硬件I2C模块与SMBus(系统管理总线)协议兼容,SMBus是一种基于I2C的通信协议,用于管理和控制电子设备。

这些特点使得STM32的硬件I2C模块成为在嵌入式系统中实现I2C通信的理想选择,提供了方便、高效和可靠的通信功能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据仓库【1】:简介

数据仓库【1】&#xff1a;简介 1、诞生背景1.1、数据仓库诞生原因1.2、历史数据积存1.3、企业数据分析需要 2、基本概述2.1、数据仓库&#xff08;Data Warehouse&#xff0c;DW&#xff09;2.2、数据仓库特点2.3、数据仓库 VS 数据库 3、技术实现3.1、数据仓库建设方案3.2、传…

『CVE』简析CVE-2023-48795:SSH协议前缀截断攻击(Terrapin攻击)

文章目录 OpenSSH 9.6更新公告Terrapin攻击 (CVE-2023-48795)基本信息利用手段利用路径利用条件利用原理及示意图危害Terrapin-Scanner 基于Terrapin的潜在风险&#xff1a;CVE-2023-46445 & 46446参考完 OpenSSH 9.6更新公告 *ssh(1), sshd(8): implement protocol extens…

第十六节TypeScript 类

1、简介 TypeScript是面向对象的JavaScript。 类描述了所创建的对象共同的属性与方法。 2、类的定义 class class_name { // 类作用域 } 定义类的关键字是class&#xff0c;后面紧跟类名&#xff0c;类可以包含以下几个模块&#xff1a; 字段 – 字段是类里面声明的变量。字…

java练习之abstract (抽象) final(最终) static(静态) 练习

1&#xff1a;分析总结&#xff1a;写出private、abstract、static、final之间能否联动使用&#xff0c;并写出分析原因 private static final 之间可以任意结合 abstract 不可以与private static final 结合使用 2&#xff1a;关于三个修饰符描述不正确的是(AD) A. static …

实习知识整理8:如何实现将商品加入购物车

情景分析&#xff1a;当我们进入商品详情页面时&#xff0c;一般会有两个按钮&#xff0c;一个是加入购物车&#xff0c;另一个是直接购买的按钮&#xff0c;我们先来看看加入购物车是如何实现的 1. 数据库表分析 需要3个表&#xff1a;商品表item、用户表user、购物车表cart 需…

基于JAVA的医院门诊预约挂号系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 功能性需求2.1.1 数据中心模块2.1.2 科室医生档案模块2.1.3 预约挂号模块2.1.4 医院时政模块 2.2 可行性分析2.2.1 可靠性2.2.2 易用性2.2.3 维护性 三、数据库设计3.1 用户表3.2 科室档案表3.3 医生档案表3.4 医生放号…

Autosar CAN开发05(从实际应用认识CAN波特率)

建议同时阅读本专栏的&#xff1a; Autosar CAN开发03&#xff08;从实际应用认识CAN总线的物理层&#xff09; Autosar CAN开发04&#xff08;从实际应用认识CAN报文&#xff09; Autosar CAN开发05&#xff08;从实际应用认识CAN波特率&#xff09; 前言 当知道了CAN的物…

STM32MP157D-DK1开发板Qt镜像构建

上篇介绍了STM32MP57-DK1开发板官方系统的烧录。那个系统包含Linux系统的基础功能&#xff0c;如果要进行Qt开发&#xff0c;还需要重新构建带有Qt功能的镜像 本篇就来介绍如何构建带有Qt功能的系统镜像&#xff0c;并在开发板中烧录构建的镜像。 1 Distribution包的构建 ST…

优化模型:MATLAB整数规划

一、整数规划介绍 1.1 整数规划的定义 若规划模型的所有决策变量只能取整数时&#xff0c;称为整数规划。若在线性规划模型中&#xff0c;变量限制为整数&#xff0c;则称为整数线性规划。 1.2 整数规划的分类 整数规划模型大致可分为两类&#xff1a; &#xff08;1&…

HAL库的常用库函数(根据学习而更新)

目录 一、常用的GPIO相关HAL库函数 1、GPIO的初始化 2、配置GPIO引脚输出电平 3、切换指定引脚的电平&#xff0c;电平的翻转 4、读取指定GPIO引脚的电平 5、结构体 GPIO_InitTypeDef &#xff08;引脚&#xff09;定义&#xff1a; 6、高低电平的表示 7、延时函数&…

Java架构师系统架构需求分析实战

目录 1 导语2 需求分析实战3 核心方法论-架构立方体4 功能性模型-模块定义5 功能性模型-模块关系图6 功能性模型-模块细化 想学习架构师构建流程请跳转&#xff1a;Java架构师系统架构设计 1 导语 架构设计的实战和思维方法的讨论&#xff0c;主要聚焦于需求分析的重要性和方…

buuctf-Misc 题目解答分解97-99

97.[BSidesSF2019]zippy 下载完就是一个流量包 追踪tcp nc -l -p 4445 > flag.zip unzip -P supercomplexpassword flag.zip Archive: flag.zip 压缩包密码 supercomplexpassword 保存为 flag.zip 解压得到flag 98.[GUET-CTF2019]虚假的压缩包 先从虚假的压缩包入手 &am…

逆向P1P2总结

字节八位 word 16位 deword 32 位 00 00 00 e8 是存储32位信息的起点 不是程序运行的起点 为什么电脑有32位与64位之分 寻址宽度 以字节为单位 0xfffffff 1 就是最大容量 转为十进制为 4294967296 / 1024 &#xff08;k&#xff09;/1024 &#xff08;kb&#xff09;/ 1…

软件测试面试八股文——基础篇

5&#xff09;错误推测法&#xff1a;是基于经验和直觉推测程序中所有可能存在的各种错误&#xff0c;从而有针对性的设计测试用例的方法 6&#xff09;正交实验法 7&#xff09;判定表法 8&#xff09;测试大纲法 3、提交缺陷的八大要素 1&#xff09;缺陷编号&#xff1a…

数据通信网络基础华为ICT网络赛道

目录 前言&#xff1a; 1.网络与通信 2.网络类型与网络拓扑 3.网络工程与网络工程师 前言&#xff1a; 数据通信网络基础是通信领域的基本概念&#xff0c;涉及数据传输、路由交换、网络安全等方面的知识。华为ICT网络赛道则是华为公司提出的一种技术路径&#xff0c;旨在通…

合并的单元格如何填充连续的序号

希望你以后碰到合并的单元格&#xff0c;不在一个个输入序号&#xff0c;用以下操作帮你输入连续的序号。 一、操作过程如下 1.有一个基准的单元格在同一列&#xff0c;而且这个基准单元格必须得是序号为1的单元格的上面的一个单元格&#xff0c;这样的话后面才能自动递增&am…

Cesium.js三维地图的实现(依托天地图CDN文件)

零、技术选型&#xff1a; Vue2、VueCli5、天地图、Cesium.js 一、通过天地图官网案例实现 需要引入天地图官方提供的CDN链接访问Cesium.js相关文件 相关文件&#xff1a; https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Cesium.js https://api.tianditu.gov.cn/…

大数据技术学习笔记(十一)—— Flume

目录 1 Flume 概述1.1 Flume 定义1.2 Flume 基础架构 2 Flume 安装3 Flume 入门案例3.1 监控端口数据3.2 实时监控单个追加文件3.3 实时监控目录下多个新文件3.4 实时监控目录下的多个追加文件 4 Flume 进阶4.1 Flume 事务4.2 Flume Agent 内部原理4.3 Flume 拓扑结构4.3.1 简单…

PyQt5和Qt designer的详细安装教程

Qt designer界面和所有组件功能的详细介绍参考&#xff1a;https://blog.csdn.net/qq_43811536/article/details/135186862?spm1001.2014.3001.5501 目录 0. 写在前面1. Anaconda创建虚拟环境2. 安装PyQt5和Qt designer3. 测试安装成功 0. 写在前面 Qt Designer是Qt提供的一种…

智慧互联网银行引领金融变革,开源网安VulHunter护航数字化发展

某银行作为国内知名的互联网银行&#xff0c;以构建“智慧型互联行”为总体战略目标&#xff0c;始终坚持科技赋能金融的理念。通过AI、大数据、云计算等数字技术与金融业务的探索融合&#xff0c;实现以更低的成本为客户提供便捷、高效和优质体验的互联网金融服务。 架构升级助…
最新文章