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_1GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO速度为50MHzGPIO_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的相应位设置为1myi2c_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.mzph.cn/news/577752.shtml

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

相关文章

MyBatis——MyBatis的缓存

MyBatis的缓存 创建工程&#xff1a; 1缓存介绍 为什么使用缓存&#xff1f; 首次访问时&#xff0c;查询数据库&#xff0c;并将数据存储到内存中&#xff1b;再次访问时直接访问缓存&#xff0c;减少IO、硬盘读写次数、提高效率 Mybatis中的一级缓存和二级缓存&#xff1f;…

【SD】通过种子数 差异强度 进行 角色融合【2】

通过 对 2个种子 进行对比 生成 2张图片 风格相符合的图片 best quality,masterpiece,chibi,full body, 我们首先生成1张图 Seed: 726932558 我们再次生成一张图 Seed: 3824894478 随机种子&#xff1a;图一 随机种子&#xff1a;图二 差异强度&#xff1a;0.2 差异强度0.4 差…

31. Ajax

简介 AJAX 是 Asynchronous JavaScript And XML 的简称。直译为&#xff0c;异步的JS和XML。AJAX的实际意义是&#xff0c;不发生页面跳转、异步载入内容并改写页面内容的技术。AJAX也可以简单的理解为通过JS向服务器发送请求。 AJAX这门技术很早就被发明&#xff0c;但是直到…

前端框架前置学习(4) AJAX

同步代码和异步代码 同步代码 浏览器按照我们书写代码的顺序一行一行地执行程序.浏览器会等待代码的解析和工作,在上一行代码完成之后才会执行下一行代码.这被称之为同步程序 逐行执行,需要原地等待结果 异步代码 异步编码技术使得程序可以在执行一个可能长期运行的任务的…

助力打造清洁环境,基于轻量级YOLOv8开发构建公共场景下垃圾堆放垃圾桶溢出检测识别系统

公共社区环境生活垃圾基本上是我们每个人每天几乎都无法避免的一个问题&#xff0c;公共环境下垃圾投放点都会有固定的值班时间&#xff0c;但是考虑到实际扔垃圾的无规律性&#xff0c;往往会出现在无人值守的时段内垃圾堆放垃圾桶溢出等问题&#xff0c;有些容易扩散的垃圾比…

将elementUI,NaiveUI的progress环形进度条设置为渐变色

需求 &#xff1a;进度条要有一个渐变效果。效果图&#xff1a; NaiveUI和elementUI的官方progress组件都是只能设置一种颜色&#xff0c;不符合需求所以改一下。 其实NaiveUI和elementUI设置进度条的实现方式基本一样都是使用svg渲染出两个path&#xff0c;第一个是底色&…

<meta name=“Keywords“ content=““ >、<meta name=“Description“ content=““ > 等用法解释

今天在看网站代码&#xff0c;发现类似<meta name"Keywords" content"" >、<meta name"Description" content"" >这样的写法&#xff0c;不知道具体代表什么意思&#xff0c;于是上网搜了一下&#xff0c;下面是在网上找到…

Python电能质量扰动信号分类(三)基于Transformer的一维信号分类模型

目录 引言 1 数据集制作与加载 1.1 导入数据 1.2 制作数据集 2 Transformer分类模型和超参数选取 2.1 定义Transformer分类模型 2.2 定义模型参数 3 Transformer模型训练与评估 3.1 模型训练 3.2 模型评估 代码、数据如下&#xff1a; 往期精彩内容&#xff1a; 电…

[内功修炼]函数栈帧的创建与销毁

文章目录 1:什么是函数栈帧2:理解函数栈帧能解决什么问题呢3:函数栈帧的创建与销毁的解析3.1:什么是栈3.2:认识相关寄存器与汇编指令相关寄存器相关汇编指令 3.3 解析函数栈帧的创建和销毁3.3.1 预备知识3.3.2 详细解析一:调用main函数,为main函数开辟函数栈帧First:push前push…

RK3588平台开发系列讲解(AI 篇)RKNN-Toolkit2 模型的加载转换

文章目录 一、Caffe 模型加载接口二、TensorFlow 模型加载接口三、TensorFlowLite 模型加载接口四、ONNX 模型加载五、DarkNet 模型加载接口六、PyTorch 模型加载接口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 RKNN-Toolkit2 目前支持 Caffe、TensorFlow、Tensor…

MySQL报错:1054 - Unknown column ‘xx‘ in ‘field list的解决方法

我在操作MySQL遇到1054报错&#xff0c;报错内容&#xff1a;1054 - Unknown column Cindy in field list&#xff0c;下面演示解决方法&#xff0c;非常简单。 根据箭头指示&#xff0c;Cindy对应的应该是VARCHAR文本数字类型&#xff0c;字符串要用引号&#xff0c;所以解决方…

web架构师编辑器内容-HTML2Canvas 截图的原理

HTML2Canvas 截图的原理 目的&#xff1a;一个canvas元素&#xff0c;上面有绘制一系列的HTML节点 局限&#xff1a;canvas中没法添加具体的Html节点&#xff0c;它只是一张画布 通过canvas.getContext(‘2d’)可以拿到canvas提供的2D渲染上下文&#xff0c;然后在里面绘制形…

使用tesla gpu 加速大模型,ffmpeg,unity 和 UE等二三维应用

我们知道tesla gpu 没有显示器接口&#xff0c;那么在windows中怎么使用加速unity ue这种三维编辑器呢&#xff0c;答案就是改变注册表来加速相应的三维渲染程序. 1 tesla gpu p40 p100 加速 在windows中使用regedit 来改变 核显配置&#xff0c; 让p100 p40 等等显卡通过核显…

【动态规划】11简单多状态 dp 问题_按摩师_C++(easy)

题目链接&#xff1a;leetcode按摩师 目录 题目解析&#xff1a; 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析&#xff1a; 题目让我们求按摩师找到最优的预约集合&#xff08;总预约时间最长&#xff09; 由题可得&#xff…

一体机定制_工控触控一体机安卓主板方案

工控一体机是一种集成化的硬件方案&#xff0c;采用了联发科MT8768八核芯片和12nm制程工艺。该芯片拥有2.0GHz的主频和IMG PowerVR GE8320图形处理GPU&#xff0c;具备强大的视频处理能力&#xff0c;并且兼容大部分的视频格式和解码能力。工控一体机搭载了Android 9.0操作系统…

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

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

单聊和群聊

TCP协议单聊 服务端&#xff1a; import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Vec…

使用ArcMap进行实测数据处理

文章目录 题目流程 题目 实验名称&#xff1a;实测数据处理 实验目的及要求&#xff1a; 1. 掌握实测点数据转为矢量点数据方法 2. 掌握数据投影变换方法 3. 掌握点数据插值方法 流程 1&#xff0c;打开ArcMap软件&#xff0c;在左菜单栏上选中File&#xff0c;然后鼠标移…

我在代码随想录|写代码|简单题理解KMP算法

本篇提纲 什么是KMPKMP有什么用什么是前缀表为什么一定要用前缀表如何计算前缀表前缀表与next数组使用next数组来匹配时间复杂度分析构造next数组使用next数组来做匹配前缀表统一减一 C代码实现前缀表&#xff08;不减一&#xff09;C实现总结 什么是KMP? 说到KMP&#xf…

HTTP前端请求

目录 HTTP 请求1.请求组成2.请求方式与数据格式get 请求示例post 请求示例json 请求示例multipart 请求示例数据格式小结 3.表单3.1.作用与语法3.2.常见的表单项 4.session 原理5.jwt 原理 HTTP 请求 1.请求组成 请求由三部分组成 请求行请求头请求体 可以用 telnet 程序测…