stm32入门学习11-硬件I2C和MPU
(一)I2C硬件电路
stm32内部有I2C的硬件电路,我们可以使用stm32的标准库函数来实现I2C,这可以为我们减少对软件资源的占用
I2C硬件电路常用的标准库函数
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
//通过结构体初始化I2Cvoid I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
//给初始化结构体赋默认值void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能I2C,初始化之后要使能其才开始工作void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
//开始I2C传输void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
//结束I2C传输void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
//发送一个字节数据uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
//接收一个字节数据void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
//发送7位地址,在最开始I2C寻址调用这个函数ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
//接收事件,在使用硬件开始传输或发送数据等操作之后都会有对应的事件需要接收判断后再执行下一个操作void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
//设置响应为,相当于软件实现I2C中的ack
我们只要使用这些库函数,按照其规定的流程进行数据的发送和接收即可,不需要我们手动在软件中模拟I2C的高低电平跳变
(二)使用库函数实现I2C数据的发送与接收
(1)发送
I2C发送流程如图,在开始传输完成后,其会产生EV5事件,我们在事件产生后即可发送地址位,成功发送后会产生EV6事件,接着发送寄存器地址,因为这里使用的是一个寄存器和一个移位寄存器来发送数据,所以我们在寄存器的数据写入到移位寄存器中正在发送(EV8事件)即可将新的数据写入寄存器,在最后一个数据位我们没有数据写入寄存器,且移位寄存器发送完毕,会产生EV8_2事件,表示发送完成,然后即可停止传输

这里我们发送一个字节后的接收响应由硬件自动接收,不需要我们手动接收响应
由于我们会频繁接收各种事件,我们可以把接收事件的函数封装成一个简单的函数,且让其超时退出,不让程序卡死

接收事件函数
void mpu_wait_flag(int event)
{unsigned int time = 10000;while (I2C_CheckEvent(I2C2, event) != SUCCESS){time--;if (time == 0){break;}}
}
按照流程,我们可以这样编写发送函数
发送函数
void mpu_write(unsigned char address, unsigned char inf)
{I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_MODE_SELECT); //EV5I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Transmitter);mpu_wait_flag(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //EV6I2C_SendData(I2C2, address);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTING); //EV8I2C_SendData(I2C2, inf);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED); //EV8_2I2C_GenerateSTOP(I2C2, ENABLE);
}
第一行我们先开始传输,第二行我们接收EV5事件,第三行我们发送7位地址,并且第三个参数为读模式还是写模式,我们选择写模式,第四行我们等待EV6事件,紧接着第五行发送要读取的寄存器地址,第六行等待寄存器地址移动到移位寄存器正在发送事件(EV8),最后第七行写要发送的数据,等待发送完成事件,最后停止传输;
(2)接收
接收数据的流程如图所示
这里一样,我们在开始之后会产生EV5事件,在传递MPU地址后会产生EV6事件,接着读取数据,这里由于我们在读取事件之后硬件电路会立刻把我们之前预设的ack响应发给从机,因此我们需要在读取最后一个数据之前把ack置0,我们这里只读取一个字节的数据,也就是要在发送MPU地址之后,读取数据之前先把ack置0,对应代码如下
unsigned char mpu_read(unsigned char address)
{unsigned char inf;I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED);I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Transmitter);mpu_wait_flag(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);I2C_SendData(I2C2, address);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED);I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_MODE_SELECT);I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Receiver);mpu_wait_flag(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);I2C_AcknowledgeConfig(I2C2, DISABLE); //ack=0mpu_wait_flag(I2C_EVENT_MASTER_BYTE_RECEIVED);inf = I2C_ReceiveData(I2C2);I2C_GenerateSTOP(I2C2, ENABLE);I2C_AcknowledgeConfig(I2C2, ENABLE);return inf;
}
第一段对应我们软件I2C的给寄存器地址操作,我们仍需要先写入寄存器地址,然后在第二段我们重新开始传输,接收EV5事件后发送MPU地址,这里第三个参数选择读模式,等待地址发送完成,之后值得注意的是我们先执行的不是读取数据,而是先把应答位置非应答,再去读取数据,读取完成后我们即可停止传输
(三)MPU-6050
经过上面两个函数的编写,我们已经可以调用上面两个函数来实现在指定外设寄存器上写数据和读数据的操作,我们即可进行MPU的初始化和读取转换数据所在的寄存器,这里就和之前使用软件模拟I2C的代码没有什么区别,因为软件我们只是模拟了I2C的波形,最终也封装成了写字节和读字节的函数
(1)初始化
(1)打开时钟和初始化GPIO
这里因为我们使用内部的I2C硬件电路,因此我们打开时钟我们要把I2C的时钟打开,stm32F03C8有两个I2C,这里使用的是I2C2,对应的SCL、SDA引脚为PB10、PB11

void mpu_rcc_init()
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}
初始化GPIO,这里要用复用开漏输出
void mpu_gpio_init()
{GPIO_InitTypeDef gpio_init;gpio_init.GPIO_Pin = SCL | SDA;gpio_init.GPIO_Mode = GPIO_Mode_AF_OD;gpio_init.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &gpio_init);
}
(2)I2C初始化
使用I2C硬件电路还要对I2C进行初始化,可以看下初始化结构体

(1)第一个参数是选择时钟速度,数值越大电平翻转频率越高,低于100KHz的是正常模式,高于100KHz的是高速模式,这里选择100KHz;
(2)第二个参数是选择模式,可以选泽I2C模式、SMBus设备模式或SMBus主控模式,这里选择I2C模式;
(3)第三个参数是选择高低电平的占空比,这里只有在高速模式下有效,有16:9和2:1两种可选,这里不是高速模式,可以随便选择;
(4)第四个参数是选择自身地址,自身可以作为从机,设置自身地址让其他主机呼叫,随便选择,只要不和MPU或其他I2C上的地址冲突即可;
(5)第五个参数是应答位设置,可以选择应答和非应答,给应答;
(6)第六个参数是选择7位地址模式还是10位地址模式,这里选择7为地址模式;
这样我们就可以初始化I2C了
void mpu_i2c_init()
{I2C_InitTypeDef i2c_init;i2c_init.I2C_ClockSpeed = 100000;i2c_init.I2C_Mode = I2C_Mode_I2C;i2c_init.I2C_DutyCycle = I2C_DutyCycle_2;i2c_init.I2C_OwnAddress1 = 0x00;i2c_init.I2C_Ack = I2C_Ack_Enable;i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_Init(I2C2, &i2c_init);I2C_Cmd(I2C2, ENABLE);
}
最后不要忘了使能I2C,否则其不工作
(3)MPU初始化
我们把时钟、gpio、I2C的初始化都集成于此,我们还要像软件那样配置寄存器来关闭MPU睡眠模式和选择时钟等功能,具体代码如下
void mpu_init()
{mpu_rcc_init();mpu_gpio_init();mpu_i2c_init();mpu_write(0x6B, 0x01); //PWR_MGMT_1 -> 0000 0001mpu_write(0x6C, 0x00); //PWR_MGMT_2 -> 0000 0000}mpu_write(0x19, 0x09); //SMPLRT_DIV -> 0000 1001mpu_write(0x1A, 0x06); //CONFIG -> 0000 0110mpu_write(0x1B, 0x18); //GYRO_CONFIG -> 0001 1000mpu_write(0x1C, 0x18); //ACCEL_CONFIG -> 0001 1000
}
(2)读取参数
最后我们选择将x轴、y轴和z轴的加速度和角速度放在一个结构体中返回,我们还要注意16位整数转为32位整数中的符号问题
结构体定义
typedef struct infs
{int x_acceleration;int y_acceleration;int z_acceleration;int x_angular_velocity;int y_angular_velocity;int z_angular_velocity;
} information;
16位整数转32为整数
int mpu_16_to_32(int original)
{int final;if (original & 0x8000){final = original | 0xFFFF0000;}return final;
}
我们只要读取MPU对应数据的寄存器即可,这里和软件模拟的操作一样
information mpu_get_inf()
{uint8_t inf_L;uint8_t inf_H;information infor;inf_H = mpu_read(0x3B);inf_L = mpu_read(0x3C);infor.x_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x3D);inf_L = mpu_read(0x3E);infor.y_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x3F);inf_L = mpu_read(0x40);infor.z_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x43);inf_L = mpu_read(0x44);infor.x_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x45); inf_L = mpu_read(0x46); infor.y_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x47); inf_L = mpu_read(0x48); infor.z_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);return infor;
}
(3)封装与声明
最后的.c 和 .h文件如下
#include "stm32f10x.h" // Device header#define SCL GPIO_Pin_10
#define SDA GPIO_Pin_11#define mpu_address 0xD0void mpu_wait_flag(int event)
{unsigned int time = 10000;while (I2C_CheckEvent(I2C2, event) != SUCCESS){time--;if (time == 0){break;}}
}void mpu_write(unsigned char address, unsigned char inf)
{I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_MODE_SELECT); //EV5I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Transmitter);mpu_wait_flag(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //EV6I2C_SendData(I2C2, address);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTING); //EV8I2C_SendData(I2C2, inf);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED); //EV8_2I2C_GenerateSTOP(I2C2, ENABLE);
}unsigned char mpu_read(unsigned char address)
{unsigned char inf;I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED);I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Transmitter);mpu_wait_flag(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);I2C_SendData(I2C2, address);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_TRANSMITTED);I2C_GenerateSTART(I2C2, ENABLE);mpu_wait_flag(I2C_EVENT_MASTER_MODE_SELECT);I2C_Send7bitAddress(I2C2, mpu_address, I2C_Direction_Receiver);mpu_wait_flag(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);I2C_AcknowledgeConfig(I2C2, DISABLE);mpu_wait_flag(I2C_EVENT_MASTER_BYTE_RECEIVED);inf = I2C_ReceiveData(I2C2);I2C_GenerateSTOP(I2C2, ENABLE);I2C_AcknowledgeConfig(I2C2, ENABLE);return inf;
}void mpu_rcc_init()
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}void mpu_gpio_init()
{GPIO_InitTypeDef gpio_init;gpio_init.GPIO_Pin = SCL | SDA;gpio_init.GPIO_Mode = GPIO_Mode_AF_OD;gpio_init.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &gpio_init);
}void mpu_i2c_init()
{I2C_InitTypeDef i2c_init;i2c_init.I2C_ClockSpeed = 100000;i2c_init.I2C_Mode = I2C_Mode_I2C;i2c_init.I2C_DutyCycle = I2C_DutyCycle_2;i2c_init.I2C_OwnAddress1 = 0x00;i2c_init.I2C_Ack = I2C_Ack_Enable;i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_Init(I2C2, &i2c_init);I2C_Cmd(I2C2, ENABLE);
}void mpu_init()
{mpu_rcc_init();mpu_gpio_init();mpu_i2c_init();mpu_write(0x6B, 0x01); //PWR_MGMT_1 -> 0000 0001mpu_write(0x6C, 0x00); //PWR_MGMT_2 -> 0000 0000}mpu_write(0x19, 0x09); //SMPLRT_DIV -> 0000 1001mpu_write(0x1A, 0x06); //CONFIG -> 0000 0110mpu_write(0x1B, 0x18); //GYRO_CONFIG -> 0001 1000mpu_write(0x1C, 0x18); //ACCEL_CONFIG -> 0001 1000
}typedef struct infs
{int x_acceleration;int y_acceleration;int z_acceleration;int x_angular_velocity;int y_angular_velocity;int z_angular_velocity;
} information;int mpu_16_to_32(int original)
{int final;if (original & 0x8000){final = original | 0xFFFF0000;}return final;
}information mpu_get_inf()
{uint8_t inf_L;uint8_t inf_H;information infor;inf_H = mpu_read(0x3B);inf_L = mpu_read(0x3C);infor.x_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x3D);inf_L = mpu_read(0x3E);infor.y_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x3F);inf_L = mpu_read(0x40);infor.z_acceleration = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x43);inf_L = mpu_read(0x44);infor.x_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x45); inf_L = mpu_read(0x46); infor.y_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);inf_H = mpu_read(0x47); inf_L = mpu_read(0x48); infor.z_angular_velocity = mpu_16_to_32((inf_H<<8) | inf_L);return infor;
}
#ifndef __MPU_H__
#define __MPU_H__typedef struct infs
{int x_acceleration;int y_acceleration;int z_acceleration;int x_angular_velocity;int y_angular_velocity;int z_angular_velocity;
} information;void mpu_init(void);
information mpu_get_inf(void);#endif
(四)主函数调用
我们只要在主函数开始时对MPU初始化,然后在循环中调用读取寄存器值的函数即可,和软件模拟实现的程序一样
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "MPU.h"
#include "Delay.h"
int main()
{mpu_init();OLED_Init();information inf;while(1){inf = mpu_get_inf();OLED_ShowSignedNum(1, 1, inf.x_acceleration, 5);OLED_ShowSignedNum(2, 1, inf.y_acceleration, 5);OLED_ShowSignedNum(3, 1, inf.z_acceleration, 5);OLED_ShowSignedNum(1, 8, inf.x_acceleration, 5);OLED_ShowSignedNum(2, 8, inf.y_acceleration, 5);OLED_ShowSignedNum(3, 8, inf.z_acceleration, 5);Delay_ms(500);}return 0;
}
(五)总结
在学习软件模拟I2C后,这里学习的是通过硬件I2C,通过库函数来实现I2C通信,读取MPU寄存器中的数据,我们对I2C的理解更加深入,对stm32的了解也更加具体
相关文章:
stm32入门学习11-硬件I2C和MPU
(一)I2C硬件电路 stm32内部有I2C的硬件电路,我们可以使用stm32的标准库函数来实现I2C,这可以为我们减少对软件资源的占用 I2C硬件电路常用的标准库函数 void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct); /…...
如何在C++、PHP、GO中使用AI生成PPT API接口
在当今快节奏的商业环境中,演示文稿的制作不仅需要快速,还需要具有吸引力和专业性。AI生成PPT API 服务提供了一种创新的解决方案,能够根据用户提供的内容自动生成演示文稿,极大地提高了效率和质量。本文将详细介绍AI生成PPT的优势…...
力扣面试150 逆波兰表达式求值 栈 模拟栈
Problem: 150. 逆波兰表达式求值 👨🏫 参考题解 class Solution {//纯数组模拟栈实现(推荐) 3 ms 36 MBpublic static int evalRPN(String[] tokens) {int[] numStack new int[tokens.length / 2 1];int index 0;for (String s : tokens) {swit…...
动手学深度学习V2每日笔记(深度卷积神经网络AlexNet)
本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1h54y1L7oe/spm_id_from333.788.recommend_more_video.0&vd_sourcec7bfc6ce0ea0cbe43aa288ba2713e56d 文档教程 https://zh-v2.d2l.ai/ 本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录&…...
室内定位:紧耦合的学习惯性里程 (TLIO)
a### TLIO论文解读:紧耦合的学习惯性测程 (TLIO) 在惯性测量单元 (IMU) 领域,如何在短时间内精确地估计位置和姿态一直是一个挑战。最近,论文《TLIO: Tight Learned Inertial Odometry》提出了一种创新的方法,通过将深度学习与扩展卡尔曼滤波器 (EKF) 紧密结合,来解决这一…...
【面试之算法篇】寻找二叉树中两个节点的最低公共祖先
题目 给定一个树的根节点root和两个子节点a,b,返回二叉树中两个节点的最低公共祖先。二叉树每个节点的值都是不同的整数 10060 12040 null 4 74和7的最低公共祖先是120,60和40的最低公共祖先是60 思路 两个节点的祖先会有多个,只有是祖先的节点才有可能会是最低公共…...
使用Unity开发编辑系统时复制物体的一些细节问题
首先是复制一个GameObject时组件中的变量内容的复制问题,这个在Unity复制对象时让私有变量也被复制的简单方法这篇博客里面做了说明,但是其实还有一个问题,就是有些时候需要被复制的物体在刚创建出来的时候需要自动执行一些操作,这…...
【C++】模版初阶+STL简介
🚀个人主页:奋斗的小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言💥1、函数模版💥1.1 函数模板概念💥1.2 函数模板格式💥1…...
Vue3中的toRef和toRefs的区别和用法
刚做了Ref和Reactive区别及使用方法笔记,再来总结一下,toRef 和 toRefs 的作用、用法、区别 1、作用和区别 toRef 和 toRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用,也就…...
【docker快捷部署系列一】docker快速入门,安装docker,解决运行Docker Quickstart Terminal出错
1、docker快速入门 视频链接 知识点概述 docker是轻量级虚拟机image是镜像 相当于虚拟机快照container是容器,相当于运行起来的虚拟机程序Dockerfile 是创建docker镜像的自动化脚本docker-compose 是一个定义和运行多个容器命令的工具,包括运行Docker…...
vulnhub靶机实战_DC-8
一、靶机下载 靶机下载链接汇总:https://download.vulnhub.com/使用搜索功能,搜索dc类型的靶机即可。本次实战使用的靶机是:DC-8系统:Debian下载链接:https://download.vulnhub.com/dc/DC-8.zip 二、靶机启动 下载完…...
如何做到项目真实性优化?保姆级写简历指南第五弹!
大家好,我是程序员鱼皮。做知识分享这些年来,我看过太多简历、也帮忙修改过很多的简历,发现很多同学是完全不会写简历的、会犯很多常见的问题,不能把自己的优势充分展示出来,导致措施了很多面试机会,实在是…...
Python Beautiful Soup介绍
在Web数据抓取和网页解析的世界里,Python以其简洁的语法和丰富的库资源成为了许多开发者的首选语言。而Beautiful Soup,作为Python中一个强大的HTML和XML解析库,更是以其易用性和灵活性赢得了广泛的赞誉。本文将带你走进Beautiful Soup的世界…...
NDI Tools汉化版的安装
目录 一、安装包下载 二、安装英文版 三、安装汉化版 NDI(Network Device Interface)即网络设备接口,是由美国 NewTek 公司开发的免费标准,它可使兼容的视频产品以高质量、低延迟、精确到帧的方式通过网络进行通讯、传输和接收广播级质量的视频,非常适合在现场直播制作…...
【JAVA多线程】AQS,JAVA并发包的核心
目录 1.概述 1.1.什么是AQS 1.2.AQS和BlockQueue的区别 1.3.AQS的结构 2.源码分析 2.1.CLH队列 2.2.模板方法的实现 2.2.1.独占模式 1.获取资源 2.释放资源 2.2.2.共享模式 1.概述 1.1.什么是AQS AQS非常非常重要,可以说是JAVA并发包(java.…...
springcloud loadbalancer nacos无损发布
前言 故事背景 jenkins部署时总是会有几秒钟接口调用报错,观察日志是因为流量被下发到已下线的服务,重启脚本在停止应用之前先调用nacos注销实例api后再重启依然会短暂出现此问题。项目架构是springcloud alibaba,通过openfeign进行微服务之间调用&…...
React原理
函数式编程 一种编程范式,概念比较多纯函数不可变值vdom和diff Vue2.x Vue3.x React 三者实现vdom细节都不同核心概念和实现思路,都一样h函数 用来生成vnode的函数 vnode数据结构 {tag: div,props: {className: div-class},children: [{tag: p,children: 测试}, ...] }pat…...
React-Native优质开源项目
React Native是由Facebook开发的一种开源框架,它允许开发者使用JavaScript和React编写原生应用,提供了一套跨平台的UI组件,可以在iOS和Android上实现一致的用户体验。在React Native的生态系统中,有许多优质的开源项目,…...
Ajax-02
一.form-serialize插件 作用:快速收集表单元素的值 const form document.querySelector(.example-form) const data serialize(form,{hash:true,empty:true}) *参数1:要获取哪个表单的数据 表单元素设置name属性,值会作为对象的属性名 建议…...
供应商较多的汽车制造业如何选择供应商协同平台?
汽车制造业的供应商种类繁多,根据供应链的不同环节和产品特性,可以大致分为以下几类。 按供应链等级分包括: 一级供应商通常具有较高的技术水平和生产能力,能够满足汽车厂商对零部件的高品质、高性能和高可靠性的要求。 二级供应…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
