当前位置: 首页 > news >正文

19:I2C一:程序模拟I2C通信时序

I2C

  • 1、什么是I2C
  • 2、I2C的通信时序
    • 2.1:起始信号
    • 2.2:停止信号
    • 2.3:主机向从机发送一个字节数据
    • 2.4:主机向从机读取一个字节数据
    • 2.5:主机接收应答
    • 2.6:主机发送应答
  • 3、程序模拟I2C的通信时序
    • 3.1:指定地址写一个字节的数据
    • 3.2:指定地址读一个字节的数据

1、什么是I2C

   I2C通信协议和串口通信USART不同,USART是异步,全双工的通信协议。而I2C通信协议是一种同步,半双工,带数据应答,支持总线挂载多设备的通信协议。USART传输数据的时候是先传输数据帧的低位,在传高位。而I2C传输数据的时候是高位先行。

在这里插入图片描述

   由上图所示:有2条总线,数据总线SDA和时钟总线SCL。其中时钟线SCL只能由主机控制,而SDA主机和从机都可以控制。

   当主机向从机发送一个字节数据时:①主机先发送一个起始信号,②然后在发送一个字节的数据(从机地址(7位)+W),然后接收从机的应答信号,③然后在发送一个字节的数据(从机寄存器的地址),然后接收一个应答信号,④然后开始发送需要发送给从机的数据,然后接收应答信号,⑤发送一个停止信号。 如下图所示:
在这里插入图片描述

   当主机读取从机一个字节的数据时:①主机先发送一个起始信号,②然后在发送一个字节的数据(从机地址(7位)+W),然后接收从机的应答信号,③然后在发送一个字节的数据(从机寄存器的地址)④然后主机在发送一个起始信号,⑤然后在发送一个字节的数据(从机地址(7位)+R),然后接收从机的应答信号,⑥然后开始读取SDA上面的数据,读取到一个字节后,给从机发送一个应答信号,如下图所示:
在这里插入图片描述

2、I2C的通信时序

2.1:起始信号

   起始信号和停止信号都是由主机进行发送,主机需要发送起始信号时:SCL高电平期间,SDA从高电平切换到低电平
在这里插入图片描述
使用程序模拟此时序代码如下:

void I2C_W_SCL(uint8_t BitValue)//拉低SCL或者释放SCL(拉高)
{GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);Delay_us(10);
}void I2C_W_SDA(uint8_t BitValue)//给SDA写数据(拉低SDA/释放SDA(拉高))
{GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);Delay_us(10);
}void MyI2C_Start(void)//起始信号
{
//	SCL(1);//释放SCLI2C_W_SDA(1);//释放SDAI2C_W_SCL(1);//释放SCLI2C_W_SDA(0);//拉低SDAI2C_W_SCL(0);//拉低SCL
}

2.2:停止信号

   主机需要发送停止信号时:SCL高电平期间,SDA从低电平切换到高电平
在这里插入图片描述

使用程序模拟此时序代码如下:

void MyI2C_Stop(void)
{I2C_W_SCL(0);I2C_W_SDA(0);I2C_W_SCL(1);I2C_W_SDA(1);
}

2.3:主机向从机发送一个字节数据

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

在这里插入图片描述
使用程序模拟此时序代码如下:

/*发送数据前,主机会发送一个起始信号,由上面的程序可知:起始信号发送完后SCL和SDA都被拉低。所以函数里面不用在拉低,直接向SDA写入数据即可。
*/
void MyI2C_SendByte(uint8_t Byte)//主机向从机发送一个字节,高位先行
{I2C_W_SDA(Byte & 0x80);//给SDA写入数据,只要Byte不是0,那么写入的就是1。因为BitActionI2C_W_SCL(1);//释放SCL,从机读取数据I2C_W_SCL(0);//拉低SCL,主机准备给SDA写入字节的次高位数据I2C_W_SDA(Byte & 0x40);//给SDA写入数据,I2C_W_SCL(1);//释放SCL,从机读取数据I2C_W_SCL(0);//拉低SCL,主机准备给SDA写入字节的次次高位数据...
}

代码优化如下:

/*发送数据前,主机会发送一个起始信号,由上面的程序可知:起始信号发送完后SCL和SDA都被拉低。所以函数里面不用在拉低,直接向SDA写入数据即可。
*/
void MyI2C_SendByte(uint8_t Byte)//主机向从机发送一个字节,高位先行
{for(uint8_t i = 0;i<8;i++){I2C_W_SDA(Byte & (0x80 >> i));//给SDA写入数据,只要Byte不是0,那么写入的就是1。因为BitActionI2C_W_SCL(1);//释放SCL,从机读取数据I2C_W_SCL(0);//拉低SCL,主机准备给SDA写入字节的次高位数据}
}

2.4:主机向从机读取一个字节数据

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

在这里插入图片描述
使用程序模拟此时序代码如下:

uint8_t I2C_R_SDA(void)//主机读SDA数据,即判断引脚的电平
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitValue;
}/*主机接收数据之前,主机会给从机发送一个字节,由上面的代码得发送完数据后此时SCL为低电平。之后释放SDA总线让从机拥有SDA总线的控制权。
*/
uint8_t MyI2C_ReceiveByte(void)
{uint8_t Byte = 0x00;//接收数据的变量I2C_W_SDA(1);//主机释放SDA,让控制权给从机,而SCL也是低电平,释放的一瞬间,从机就给SDA写入了数据I2C_W_SCL(1);if(I2C_R_SDA() == 1)//读取第一位数据{Byte |= 0x80;}I2C_W_SCL(0);//主机拉低SCL,让从机给SDA写入数据	I2C_W_SCL(1);//主机拉高SCL,准备开始读取SDA上面的数据if(I2C_R_SDA() == 1){Byte |= 0x40;}I2C_W_SCL(0);//主机拉低SCL,让从机给SDA写入数据	...return Byte;
}

代码优化如下:

uint8_t MyI2C_ReceiveByte(void)
{uint8_t Byte = 0x00;//接收数据的变量I2C_W_SDA(1);//主机释放SDA,让控制权给从机for(uint8_t i =0; i<8;i++){I2C_W_SCL(1);//主机拉高SCL,准备开始读取SDA上面的数据if(I2C_R_SDA() == 1){Byte |= (0x80 >> i);}	I2C_W_SCL(0);//主机拉低SCL,准备让从机给SDA写入数据	}return Byte;
}

2.5:主机接收应答

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

在这里插入图片描述

使用程序模拟此时序代码如下:

uint8_t I2C_R_SDA(void)//主机读SDA数据,即判断引脚的电平
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitValue;
}uint8_t MyI2C_ReceiveACK(void)//主机接收应答
{
/*主机发送完一个字节后,SCL为低电平,等待从机给SDA上面写入数据,如果拉低则代表接收成功
*/uint8_t ACKBit;I2C_W_SDA(1);//主机释放SDA,让控制权给从机I2C_W_SCL(1);//主机释放SCL,准备开始读取SDA上面的数据ACKBit = I2C_R_SDA();I2C_W_SCL(0);//主机拉低SCL,进入下一个时序单元,主机准备给SDA写入字节的数据return ACKBit;
}

2.6:主机发送应答

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

void MyI2C_SendACK(uint8_t ACKBit)//主机发送应答
{
/*从机发送完一个字节后,SCL为低电平,等待主机给SDA上面写数据,如果拉低代表接收成功。
*/I2C_W_SDA(ACKBit);//主机给SDA写入应答信号,0为应答,1为非应答I2C_W_SCL(1);//主机拉高SCL,让从机读取应答信号I2C_W_SCL(0);//主机拉低SCL,准备写入数据
}

3、程序模拟I2C的通信时序

3.1:指定地址写一个字节的数据

在这里插入图片描述
用程序模拟I2C时序实现如上图的波形:
①I2C.c文件使用程序模拟I2C时序程序如下:

#include "stm32f10x.h"                 
#include "Delay.h"                 //#define SCL(x)          GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)(x))
//#define SDA(x)          GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)(x))void I2C_W_SCL(uint8_t BitValue)//拉低SCL/释放SCL(拉高)
{GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);Delay_us(10);
}void I2C_W_SDA(uint8_t BitValue)//给SDA写数据(拉低SDA/释放SDA(拉高))
{GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);Delay_us(10);
}uint8_t I2C_R_SDA(void)//主机读SDA数据,即判断引脚的电平
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitValue;
}void MyI2C_Init(void)
{//1. 使能挂载在APB2总线上面的片上外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//2. 对GPIO_PA10/PA11进行配置GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//输出开漏模式,0才有驱动能力,开漏模式没有输出低电平时,也可以作为输入GPIOInitStruct.GPIO_Speed = GPIO_Speed_50MHz;//最大输出速度GPIO_Init(GPIOB,&GPIOInitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_10 | GPIO_Pin_11);//先给输出高电平,释放总线//PB10连接SCL。PB11连接SDA
}void MyI2C_Start(void)//起始信号
{I2C_W_SDA(1);//释放SDAI2C_W_SCL(1);//释放SCLI2C_W_SDA(0);//拉低SDAI2C_W_SCL(0);//拉低SDA
}void MyI2C_Stop(void)
{I2C_W_SCL(0);I2C_W_SDA(0);I2C_W_SCL(1);I2C_W_SDA(1);
}void MyI2C_SendByte(uint8_t Byte)//主机向从机发送一个字节,高位先行
{for(uint8_t i = 0;i<8;i++){I2C_W_SDA(Byte & (0x80 >> i));//给SDA写入数据,只要Byte不是0,那么写入的就是1。因为BitActionI2C_W_SCL(1);//释放SCL,从机读取数据I2C_W_SCL(0);//拉低SCL,主机准备给SDA写入字节的次高位数据}
}uint8_t MyI2C_ReceiveByte(void)
{uint8_t Byte = 0x00;//接收数据的变量I2C_W_SDA(1);//主机释放SDA,让控制权给从机for(uint8_t i =0; i<8;i++){I2C_W_SCL(1);//主机释放SCL,准备开始读取SDA上面的数据if(I2C_R_SDA() == 1){Byte |= (0x80 >> i);}	I2C_W_SCL(0);//主机拉低SCL,让从机给SDA写入数据	}return Byte;
}void MyI2C_SendACK(uint8_t ACKBit)//主机发送应答
{
/*从机发送完一个字节后,SCL为低电平,等待主机给SDA上面写数据,如果拉低代表接收成功。
*/I2C_W_SDA(ACKBit);I2C_W_SCL(1);I2C_W_SCL(0);
}uint8_t MyI2C_ReceiveACK(void)//主机接收应答
{
/*主机发送完一个字节后,SCL为低电平,等待从机给SDA上面写入数据,如果拉低则代表接收成功
*/uint8_t ACKBit;I2C_W_SDA(1);//主机释放SDA,让控制权给从机I2C_W_SCL(1);//主机释放SCL,准备开始读取SDA上面的数据ACKBit = I2C_R_SDA();I2C_W_SCL(0);//主机拉低SCL,进入下一个时序单元,主机准备给SDA写入字节的数据return ACKBit;
}

②主函数文件模拟波形的程序如下:

#include "stm32f10x.h"   
#include "MyI2C.h"
int main(void)
{MyI2C_Init();MyI2C_Start();//发送一个起始信号MyI2C_SendByte(0xD0);//发送一个字节的数据(从机地址7位+W),0表示写,1表示读MyI2C_ReceiveACK();//接收从机应答信号MyI2C_SendByte(0x19);//发送一个字节的数据(从机中的寄存器地址)MyI2C_ReceiveACK();//接收从机应答信号MyI2C_SendByte(0xAA);//发送一个字节的数据(需要发送给从机的数据)MyI2C_ReceiveACK();//接收从机应答信号MyI2C_Stop();//发送一个停止信号
}

3.2:指定地址读一个字节的数据

在这里插入图片描述

#include "stm32f10x.h"   
#include "MyI2C.h"
int main(void)
{uint8_t Data;MyI2C_Init();MyI2C_Start();//发送一个起始信号MyI2C_SendByte(0xD0);//发送一个字节的数据(从机地址7位+W),0表示写,1表示读MyI2C_ReceiveACK();//接收从机应答信号MyI2C_SendByte(0x19);//发送一个字节的数据(从机中的寄存器地址)MyI2C_ReceiveACK();//接收从机应答信号MyI2C_Start();//发送一个起始信号MyI2C_SendByte(0xD1);//发送一个字节的数据(从机地址7位+R),0表示写,1表示读MyI2C_ReceiveACK();//接收从机应答信号Data = MyI2C_ReceiveByte();//主机接收一个字节的数据MyI2C_SendACK(1);//主机发送非应答信号MyI2C_Stop();//发送一个停止信号
}

相关文章:

19:I2C一:程序模拟I2C通信时序

I2C 1、什么是I2C2、I2C的通信时序2.1&#xff1a;起始信号2.2&#xff1a;停止信号2.3&#xff1a;主机向从机发送一个字节数据2.4&#xff1a;主机向从机读取一个字节数据2.5&#xff1a;主机接收应答2.6&#xff1a;主机发送应答 3、程序模拟I2C的通信时序3.1&#xff1a;指…...

最佳实践 · MySQL 分区表实战指南

引言 在数据量急剧增长的今天&#xff0c;传统的数据库管理方式可能无法有效处理海量数据的存储和查询需求。MySQL 提供了分区表功能&#xff0c;这不仅能够帮助优化性能&#xff0c;还能简化数据管理过程。分区表允许将数据表拆分成多个逻辑上的分区&#xff0c;每个分区可以…...

详细介绍 Redis 列表的应用场景

Redis 的列表&#xff08;List&#xff09;数据类型有以下一些主要应用场景&#xff1a; 一、消息队列 生产者-消费者模式 生产者可以使用LPUSH命令将消息从列表的左端&#xff08;头部&#xff09;插入到 Redis 列表中。消费者则使用BRPOP或RPOP命令从列表的右端&#xff08;…...

游戏如何检测加速外挂

在游戏面临的众多外挂风险中&#xff0c;除了常见的内存修改挂、注入挂等作弊手段&#xff0c;黑灰产还常用「加速」手段实现作弊。 游戏安全风险分布占比图 「加速」顾名思义是指改变游戏内的速度。游戏在运行中需要以帧为单位播放画面&#xff0c;而计算每帧动画播放所需时间…...

【STM32 HAL库】OLED显示模块

【STM32 HAL库】OLED显示模块 前言理论OLED基本参数OLED基本驱动原理OLED坐标轴 应用CubeMx配置底层函数代码高层封装函数printf显示函数 前言 本文为笔者学习 OLED 的总结&#xff0c;基于keysking的视频内容&#xff0c;如有错误&#xff0c;欢迎指正 理论 OLED基本参数 …...

Redis---卸载Redis

简介 在Linux系统或者Mac系统卸载Redis。 步骤 1、停止Redis服务 #查看Redis服务进行 ps -ef | grep redis #停止Redis服务 redis-cli -a 111111 -p 6370 shutdown #再次查看Redis服务进程 ps -ef | grep redis2、删除/usr/local/bin目录下与Redis相关的文件 #查找Redis相…...

《C++模板元编程实战》阅读记录

目录 写在前面基本介绍第一部分 元编程基础技术第1章 基本技巧1.1元函数与type_traits1.1.1 元函数介绍 写在前面 这本书之前是在一片公众号里面介绍的&#xff0c;我觉的不错&#xff0c;想着提高一下自己C的水平&#xff0c;就买了一本&#xff0c;大概是2022年下半年买的&a…...

pybind11 学习笔记

pybind11 学习笔记 0. 一个例子1. 官方文档1.1 Installing the Library1.1.1 Include as A Submodule1.1.2 Include with PyPI1.1.3 Include with Conda-forge 1.2 First Steps1.2.1 Separate Files1.2.2 PYBIND11_MODULE() 宏1.2.3 example.cpython-38-x86_64-linux-gnu.so 的…...

36.贪心算法3

1.坏了的计算器&#xff08;medium&#xff09; . - 力扣&#xff08;LeetCode&#xff09; 题目解析 算法原理 代码 class Solution {public int brokenCalc(int startValue, int target) {// 正难则反 贪⼼int ret 0;while (target > startValue) {if (target % 2 0…...

htop(1) command

文章目录 1.简介2.格式3.选项4.交互式命令5.示例6.小结参考文献 1.简介 htop 是一种交互式、跨平台的基于 ncurses 的进程查看器。 类似于 top&#xff0c;但 htop 允许您垂直和水平滚动&#xff0c;并使用指向设备(鼠标)进行交互。您可以观察系统上运行的所有进程&#xff0…...

ODrive学习——添加485编码器支持

系列文章目录 文章目录 系列文章目录前言一、端口处理二、在Encoder中引入新的类型1.增加485类型2.增加串口的初始化操作3.数据处理 总结 前言 尝试在ODrive中添加485型的编码器的支持 一、端口处理 计划使用PA2及PA3作为485通信的端口。这样首先要把外部温度传感器的I/O口给…...

在OSX上: 使用brew安装nginx 后,在通过编译安装第三方模块

1. 下载nginx安装包nginx: download 2. mac环境编译源码需要安装pcre、openssl等第三方依赖&#xff0c;可参考在OSX上: 使用brew安装nginx 后&#xff0c;在通过编译安装第三方模块 - ZhYQ_note - 博客园 3. nginx可支持的配置参考Building nginx from Sources 4. 执行 ./…...

C++初阶学习第六弹------标准库中的string类

目录 一.标准库中的string类 二.string的常用接口函数 2.1string类对象的构造 2.2 string的容量操作 2.3 string类的访问与遍历 2.4 string类对象的修改 2.5 string类常用的非成员函数 三、总结 一.标准库中的string类 可以简单理解成把string类理解为变长的字符数组&#x…...

Linux基础-Makefile的编写、以及编写第一个Linux程序:进度条(模拟在 方便下载的同时,更新图形化界面)

目录 一、Linux项目自动化构建工具-make/Makefile ​编辑 背景&#xff1a; makefile小技巧&#xff1a; 二、Linux第一个小程序&#xff0d;进度条 先导&#xff1a; 1.如何利用/r,fflush(stdout)来实现我们想要的效果&#xff1b; 2.写一个倒计时&#xff1a; 进度条…...

华为云DevSecOps和DevOps

目录 1.华为云DevSecOps和DevOps 1.1 DevSecOps 1.1.1 核心功能 1.1.2 优势 1.2 DevOps 1.2.1 核心功能 1.2.2 优势 1.3 DevOps和DevSecOps的区别 1.3.1 安全性集成 1.3.2 自动化的安全工具 1.3.3 团队协作 1.3.4 质量与合规性 1.3.5 成本与风险管理 1.3.5 总结 …...

RESTful API设计中的GET与POST:何时及为何成为首选?

RESTful API设计中的GET与POST&#xff1a;何时及为何成为首选&#xff1f; 在RESTful API的设计过程中&#xff0c;HTTP方法&#xff08;GET、POST、PUT、DELETE等&#xff09;作为资源的操作标识&#xff0c;扮演着至关重要的角色。然而&#xff0c;在实际开发中&#xff0c…...

秋招自我介绍

1min 尊敬的面试官您好&#xff0c;感谢您百忙之中参加我的面试。我是来自北京大学的王峰。 在实习经历方面&#xff0c;我曾在美团和小米公司实习。在美团主要负责核身、质检、词云项目。 在核身项目中&#xff0c;完整的经历从0-1的项目上线过程 在质检项目中&#xff0c;进…...

html加载页面

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>算数模一体化</title> </head><b…...

【数据可视化】Arcgis api4.x 热力图、时间动态热力图、timeSlider时间滑块控件应用 (超详细、附免费教学数据、收藏!)

1.效果 目录 1.效果 2.安装配置 3.热力图 4.TimeSlider滑块应用 4.1 时间滑块控件 4.2 添加控件 5.时间动态热力图 2.安装配置 这里不教大家如何在前端框架使用arcgis api。不过npm安装、css如何引入、教学数据存放与图层加载的教程&#xff0c;可以浏览我之前发的一篇文…...

WEB攻防-JavaWweb项目JWT身份攻击组件安全访问控制

知识点&#xff1a; 1、JavaWeb常见安全及代码逻辑&#xff1b; 2、目录遍历&身份验证&逻辑&JWT&#xff1b; 3、访问控制&安全组件&越权&三方组件&#xff1b; 演示案例&#xff1a; JavaWeb-WebGoat8靶场搭建使用 安全问题-目录遍历&身份认…...

OpenClaw监控告警方案:Qwen3-14B驱动服务器异常检测

OpenClaw监控告警方案&#xff1a;Qwen3-14B驱动服务器异常检测 1. 为什么需要智能化的服务器监控 作为个人站长&#xff0c;我经历过太多次深夜被服务器宕机惊醒的噩梦。传统监控工具要么配置复杂&#xff08;比如PrometheusGrafana全家桶&#xff09;&#xff0c;要么告警方…...

2025医药AI全景:数智赋能新纪元,Linux基础开发工具 --- vim。

2025医药行业数智赋能与AI应用全景分析 行业背景与核心驱动力 全球医药行业正经历数字化转型浪潮&#xff0c;AI技术、大数据分析、物联网成为关键驱动力。2025年市场规模预计突破2.5万亿美元&#xff0c;年复合增长率达12%。政策支持&#xff08;如FDA加速AI医疗审批&#xff…...

告别会议记录烦恼:5分钟掌握Windows实时语音转文字神器

告别会议记录烦恼&#xff1a;5分钟掌握Windows实时语音转文字神器 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech 还在为会议记录焦头烂额吗&#xff1f;TMSpeech这款免费开源的Windows实时语音转文字工具&#xf…...

从原理图到比特流:手把手解读Vivado里那个神秘的SPI x4配置电路图(附Mode引脚设置对照表)

深入解析Vivado SPI x4配置电路&#xff1a;从原理图到硬件实现的完整指南 在FPGA开发中&#xff0c;SPI Flash配置电路的正确设计直接关系到系统能否正常启动和工作。许多工程师在第一次接触Xilinx Vivado提供的官方SPI x4配置电路图时&#xff0c;往往会对其中各种网络标签和…...

RMBG-2.0镜像安全加固:非root用户运行、网络隔离、资源限制配置指南

RMBG-2.2镜像安全加固&#xff1a;非root用户运行、网络隔离、资源限制配置指南 在AI应用快速部署的今天&#xff0c;我们往往更关注模型的效果和速度&#xff0c;而忽略了运行环境的安全性。想象一下&#xff0c;你精心部署了一个图像处理服务&#xff0c;结果因为一个简单的…...

SEO_如何通过内容优化有效提升SEO效果?(403 )

如何通过内容优化有效提升SEO效果&#xff1f; 在当今竞争激烈的网络环境中&#xff0c;如何通过内容优化有效提升SEO效果&#xff0c;成为了每一个网站运营者的关键问题。搜索引擎优化&#xff08;SEO&#xff09;是一门艺术&#xff0c;需要我们在内容策略和技术手段上不断探…...

OpenClaw技能市场挖掘:10个适配Kimi-VL-A3B-Thinking的多模态自动化

OpenClaw技能市场挖掘&#xff1a;10个适配Kimi-VL-A3B-Thinking的多模态自动化 1. 为什么需要为多模态模型定制技能&#xff1f; 当我第一次把Kimi-VL-A3B-Thinking模型接入OpenClaw时&#xff0c;发现一个有趣现象&#xff1a;这个擅长图文理解的多模态模型&#xff0c;在执…...

CAN总线终端电阻原理与工程实践详解

1. CAN总线终端电阻的核心作用解析在工业控制和汽车电子领域&#xff0c;CAN总线是最常用的现场总线之一。作为从业十余年的嵌入式工程师&#xff0c;我处理过无数CAN总线异常案例&#xff0c;其中约30%的通信故障都与终端电阻配置不当有关。120Ω这个看似简单的参数&#xff0…...

从零到一:基于XXL-JOB构建企业级分布式任务调度中心实战指南

1. 为什么选择XXL-JOB作为分布式任务调度方案 第一次接触分布式任务调度时&#xff0c;我像大多数开发者一样面临选择困难。市面上既有成熟的商业产品&#xff0c;也有各种开源方案。经过多个项目的实战验证&#xff0c;XXL-JOB以其轻量级架构和易用性脱颖而出。这个由国内开发…...

【PythonAI】2.1.2 数据处理的瑞士军刀:初识Pandas库(2. 快速入门示例)

#pandas_dataframe.py import pandas as pd# 创建DataFrame data {姓名: [张三, 李四, 王五, 赵六],年龄: [20, 21, 19, 22],专业: [计算机, 会计, 电商, 物流],成绩: [85.5, 92.0, 78.5, 88.0] }df pd.DataFrame(data)# 查看数据 print(df.head(2)) # 查看前2行 print(…...