STM32——I2C外设总线

news2025/1/10 1:26:51

文章目录

  • 一、I2C外设简介
  • 二、I2C框图
  • 三、I2C基本结构
  • 四、主机发送
  • 五、主机接收
  • 六、I2C的中断请求
  • 七、软件/硬件波形对比
  • 八、硬件I2C读写MPU6050
    • 电路设计
    • 关键代码
    • 状态监控函数

一、I2C外设简介

  • STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担【对比USART外设是串口通信的的硬件收发器】

  • 支持多主机模型}【分为固定多主机和可变多主机,STM32为可变多主机】

  • 支持7位/10位地址模式

    • 10位地址模式下,发送的前2个字节为地址,其中前5位是10位寻址的标志位(11110),后10位是地址位
  • 支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)

  • 支持DMA

  • 兼容SMBus协议(主要用于电源管理系统中)

  • STM32F103C8T6 硬件I2C资源:I2C1、I2C2

二、I2C框图

在这里插入图片描述

  • 主要操作控制寄存器(CR),数据寄存器(DR),状态寄存器(SR)

  • 引脚设定
    在这里插入图片描述

  • 当数据从数据寄存器转到移位寄存器时,就会置状态寄存器TXE为1,表示发送寄存器为空

  • 当数据从移位寄存器转到接收寄存器时,就会置状态寄存器RXNE为1,表示接收寄存器非空

  • 自身地址寄存器:设定从机地址

  • 双地址寄存器:也是设定从机地址

  • 比较器:stm32作为从机时有从机地址,会将收到的寻址通过比较器进行判断

三、I2C基本结构

在这里插入图片描述

  • I2C通信是高位先行
  • 使用硬件I2C时,GPIO口的模式为复用开漏输出
  • 对于SDA线的GPIO口,可以完成复用开漏输出和复用功能输入,【硬件I2C使用复用开漏模式,软件I2C采用通用开漏模式】
    在这里插入图片描述

四、主机发送

在这里插入图片描述

  • 起始条件写1,当起始条件发出后自动清零,接口在生成起始条件后自动从从模式切换到主模式
    在这里插入图片描述
  • EV5事件修改了SB标志位,也是由硬件自动清零
    在这里插入图片描述
  • EV6事件修改ADDR标志位,在主模式下表示地址发送结束
    在这里插入图片描述
  • EV8事件修改TXE标志位,此时数据寄存器为空,移位寄存器非空,可以写入新的数据到DR中,该状态表示移位寄存器正在发送数据
  • EV8_2事件修改BTF标志位,表示字节发送结束
    在这里插入图片描述
  • 停止条件P写1
    在这里插入图片描述

五、主机接收

在这里插入图片描述

  • 应答位控制寄存器ACK的配置
    在这里插入图片描述
  • EV7事件修改RXNE标志位,此时DR寄存器非空,移位寄存器为空

六、I2C的中断请求

在这里插入图片描述

七、软件/硬件波形对比

在这里插入图片描述

  • I2C同步时序对于波形的要求不高,硬件I2C的波形更加标准

八、硬件I2C读写MPU6050

电路设计

在这里插入图片描述

关键代码

MPU6050.c

#include "stm32f10x.h"                  // Device header
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS		0xD0
//等待和超时退出函数
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t Timeout;
	Timeout = 10000;
	while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)
	{
		Timeout --;
		if (Timeout == 0)
		{
			break;
		}
	}
}

//指定地址写
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	I2C_GenerateSTART(I2C2, ENABLE);//生成起始条件
	/*非阻塞式函数需要通过状态标志位判断是否完成*/
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//检查EV5事件
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);//发送7位地址,读写标志位由第三个参数决定,该函数自带接收应答的过程【接收数据也自带发送应答功能】
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//检查EV6事件
	
	I2C_SendData(I2C2, RegAddress);//将数据写入DR寄存器,硬件自动转到移位寄存器
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);//检查EV8事件
	
	I2C_SendData(I2C2, Data);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);//检查EV8——2事件
	
	I2C_GenerateSTOP(I2C2, ENABLE);//生成终止条件
}
//指定地址读,先指定地址写,再调用当前地址读
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	//指定地址写
	I2C_GenerateSTART(I2C2, ENABLE);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	
	I2C_SendData(I2C2, RegAddress);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
	//当前地址读
	I2C_GenerateSTART(I2C2, ENABLE);//重复起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);//发送7位地址,读写标志位由第三个参数决定,不是发送则则置1,发送则为0
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//EV6事件
	/*如果只需要接收一个字节,则在EV6事件之后需要ACK置0且配置stop标志位,否则会多读取一个字节
	如果是接收多个字节则直接等待EV7事件,在EV7_1事件之前ACK置0且配置stop标志位为1*/
	I2C_AcknowledgeConfig(I2C2, DISABLE);//配置ACK应答位为0
	I2C_GenerateSTOP(I2C2, ENABLE);//配置停止位
	
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);//等待EV7事件
	Data = I2C_ReceiveData(I2C2);//将数据读取到DR寄存器,硬件自动转到移位寄存器
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);//恢复ACK应答位为1,方便指定地址收多个字节
	
	return Data;
}
//硬件I2C初始化和指定地址写
void MPU6050_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//I2C初始化
	I2C_InitTypeDef I2C_InitStructure;
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_ClockSpeed = 50000;//最大400KHz
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	/*在标准速度下占空比为1:1,在快速模式下设置才有用,有2个参数可以选择,
	低电平:高电平分别是16:9和2:1,因为在scl低电平时sda会切换电平,
	此时适当多分配低电平时间可以在快速模式下完成电平变化。*/
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//配置ack应答位
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//stm32作为从机可以响应多少位地址
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;//作为从机时设置自身地址1
	I2C_Init(I2C2, &I2C_InitStructure);
	
	I2C_Cmd(I2C2, ENABLE);
	
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);
}

uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}
//获取数据寄存器函数,参数为指针,指向各个数据寄存器的地址
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
	uint8_t DataH, DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
	*AccX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	*AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	*AccZ = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	*GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	*GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	*GyroZ = (DataH << 8) | DataL;
}

MPU6050.h

#ifndef __MPU6050_H
#define __MPU6050_H

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);

#endif

MPU6050_Reg.h
使用宏定义,将寄存器地址用一个字符串表示

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H

#define	MPU6050_SMPLRT_DIV		0x19
#define	MPU6050_CONFIG			0x1A
#define	MPU6050_GYRO_CONFIG		0x1B
#define	MPU6050_ACCEL_CONFIG	0x1C

#define	MPU6050_ACCEL_XOUT_H	0x3B
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

#define	MPU6050_PWR_MGMT_1		0x6B
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"

uint8_t ID;
int16_t AX, AY, AZ, GX, GY, GZ;

int main(void)
{
	OLED_Init();
	MPU6050_Init();
	
	OLED_ShowString(1, 1, "ID:");
	ID = MPU6050_GetID();
	OLED_ShowHexNum(1, 4, ID, 2);
	
	while (1)
	{
		MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);
		OLED_ShowSignedNum(2, 1, AX, 5);
		OLED_ShowSignedNum(3, 1, AY, 5);
		OLED_ShowSignedNum(4, 1, AZ, 5);
		OLED_ShowSignedNum(2, 8, GX, 5);
		OLED_ShowSignedNum(3, 8, GY, 5);
		OLED_ShowSignedNum(4, 8, GZ, 5);
	}
}

状态监控函数

EV事件可以表示多个标志位的状态,采用如下三种方式可以获取状态标志位,常用的方式是第一种,可以读取多个标志位

/**
 * @brief
 ****************************************************************************************
 *
 *                         I2C State Monitoring Functions
 *                       
 ****************************************************************************************   
 * This I2C driver provides three different ways for I2C state monitoring
 *  depending on the application requirements and constraints:
 *        
 *  
 * 1) Basic state monitoring:
 *    Using I2C_CheckEvent() function:
 *    It compares the status registers (SR1 and SR2) content to a given event
 *    (can be the combination of one or more flags).
 *    It returns SUCCESS if the current status includes the given flags 
 *    and returns ERROR if one or more flags are missing in the current status.
 *    - When to use:
 *      - This function is suitable for most applications as well as for startup 
 *      activity since the events are fully described in the product reference manual 
 *      (RM0008).
 *      - It is also suitable for users who need to define their own events.
 *    - Limitations:
 *      - If an error occurs (ie. error flags are set besides to the monitored flags),
 *        the I2C_CheckEvent() function may return SUCCESS despite the communication
 *        hold or corrupted real state. 
 *        In this case, it is advised to use error interrupts to monitor the error
 *        events and handle them in the interrupt IRQ handler.
 *        
 *        @note 
 *        For error management, it is advised to use the following functions:
 *          - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
 *          - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs.
 *            Where x is the peripheral instance (I2C1, I2C2 ...)
 *          - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler()
 *            in order to determine which error occurred.
 *          - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()
 *            and/or I2C_GenerateStop() in order to clear the error flag and source,
 *            and return to correct communication status.
 *            
 *
 *  2) Advanced state monitoring:
 *     Using the function I2C_GetLastEvent() which returns the image of both status 
 *     registers in a single word (uint32_t) (Status Register 2 value is shifted left 
 *     by 16 bits and concatenated to Status Register 1).
 *     - When to use:
 *       - This function is suitable for the same applications above but it allows to
 *         overcome the limitations of I2C_GetFlagStatus() function (see below).
 *         The returned value could be compared to events already defined in the 
 *         library (stm32f10x_i2c.h) or to custom values defined by user.
 *       - This function is suitable when multiple flags are monitored at the same time.
 *       - At the opposite of I2C_CheckEvent() function, this function allows user to
 *         choose when an event is accepted (when all events flags are set and no 
 *         other flags are set or just when the needed flags are set like 
 *         I2C_CheckEvent() function).
 *     - Limitations:
 *       - User may need to define his own events.
 *       - Same remark concerning the error management is applicable for this 
 *         function if user decides to check only regular communication flags (and 
 *         ignores error flags).
 *     
 *
 *  3) Flag-based state monitoring:
 *     Using the function I2C_GetFlagStatus() which simply returns the status of 
 *     one single flag (ie. I2C_FLAG_RXNE ...). 
 *     - When to use:
 *        - This function could be used for specific applications or in debug phase.
 *        - It is suitable when only one flag checking is needed (most I2C events 
 *          are monitored through multiple flags).
 *     - Limitations: 
 *        - When calling this function, the Status register is accessed. Some flags are
 *          cleared when the status register is accessed. So checking the status
 *          of one Flag, may clear other ones.
 *        - Function may need to be called twice or more in order to monitor one 
 *          single event.
 *            
 */

/**
 * 
 *  1) Basic state monitoring
 *******************************************************************************
 */
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
/**
 * 
 *  2) Advanced state monitoring
 *******************************************************************************
 */
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx);
/**
 * 
 *  3) Flag-based state monitoring
 *******************************************************************************
 */
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
/**
 *
 *******************************************************************************
 */

void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);

#ifdef __cplusplus
}
#endif

参考视频:江科大自化协

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

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

相关文章

Go语言jwt无感刷新以及解决SSO单点登录限制

前言 为什么使用JWT&#xff1f; Jwt提供了生成token以及token验证的方法&#xff0c;而token是一种不用存储在服务端&#xff0c;只需要由用户携带即可实现认证的一种方式。在介绍JWT之前&#xff0c;我们也应该先了解cookie和session。 Cookie和Session 为每一位用户设定…

PLSQL Developer 代码助手卡顿优化

支持付费优化 原因分析 代码助手卡顿来源于&#xff08;不考虑网络和软件版本等影响&#xff09; A.从已连接的数据库的数据字典中&#xff0c;读取该表的列信息B.将读取到的列信息返回到plsql编辑器&#xff0c;并进行字符处理&#xff0c;然后显示如何优化B 这个勾勾是维…

【GPLT 二阶题目集】L2-034 口罩发放

为了抗击来势汹汹的 COVID19 新型冠状病毒&#xff0c;全国各地均启动了各项措施控制疫情发展&#xff0c;其中一个重要的环节是口罩的发放。 某市出于给市民发放口罩的需要&#xff0c;推出了一款小程序让市民填写信息&#xff0c;方便工作的开展。小程序收集了各种信息&#…

redis的配置文件

目录 介绍 1. 单位的设置方式 2. 可以包含其他文件内容 3. 网络配置相关 4. 通用 5. 安全 6. 限制 redis的配置文件名为redis.conf&#xff0c;一般会安装在/etc目录下。 如果找不到该文件可以使用find命令查找。 find . -name redis.conf 介绍 1. 单位的设置方式 只支持字…

client-go监听apiserver,监听http2逻辑分析

前言 最近做项目&#xff0c;需要写一个controller&#xff08;k8s的插件&#xff09;&#xff0c;需要从k8s的apiserver取数据&#xff0c;就用了自带的client-go&#xff0c;但是client-go是怎么从apiserver获取数据的一直没有研究过&#xff0c;只是看网上&#xff0c;看官…

Hudi系列10:Flink流式插入

文章目录流式插入概述一. Hudi流式插入案例1(datagen)1.1 准备工作1.2 源端准备1.3 目标端表准备1.4 ETL准备1.5 数据验证1.6 通过SPARK SQL查看数据二. Hudi流式插入案例2(Kafka)2.1 准备工作2.2 源端准备2.2.1 创建kafka的topic (hudi_flink)2.2.2 Flink SQL Client消费kafka…

卷积神经网络中的权值共享和局部连接

卷积神经网络中的权值共享和局部连接卷积神经网络的两大特点权值共享全连接卷积神经网络的两大特点 权值共享&#xff0c;就是输入一张图&#xff0c;用一个filter去扫这张图&#xff0c;filter里面的数就叫权重&#xff0c;这张图每个位置都是被同样的filter扫的&#xff0c;…

Flink官方例子解析:WordCount

1. 简介 今天介绍的是官方子项目flink-examples-streaming里面的WordCount例子。 WordCount &#xff0c;中文&#xff1a;单词统计&#xff0c;是大数据计算常用的例子。 2. WordCount需要实现的功能 监听指定目录下的文件&#xff0c;读取文件的文本内容&#xff1b;如果未…

Python继承机制及其使用

Python 类的封装、继承、多态 3 大特性&#xff0c;前面章节已经详细介绍了 Python 类的封装&#xff0c;本节继续讲解 Python 类的继承机制。继承机制经常用于创建和现有类功能类似的新类&#xff0c;又或是新类只需要在现有类基础上添加一些成员&#xff08;属性和方法&#…

RASP技术进阶系列(三):重大漏洞自动化热修复

在上篇文章《RASP技术进阶系列&#xff08;二&#xff09;&#xff1a;东西向Web流量智能检测防御》中提到&#xff0c;在企业日常安全运营以及HW场景下&#xff0c;应用漏洞攻击应急响应和恶意流量溯源分析是安全团队的重点工作。在恶意流量溯源方面&#xff0c;指向攻击来源的…

趁着你对象吃泡面的功夫,我修复了误删除的文件

文章目录前言一. linux下文件删除原理1.1 文件删除原理的简单介绍1.2 测试inode号是否容易被覆盖&#xff1f;二. 实验测试过程2.1 实验环境&#xff1a;2.2 新增一块硬盘测试2.3 对磁盘分区2.3.1 分区&#xff08;使用fdisk分区&#xff09;2.3.2 格式化&#xff0c;创建目录挂…

网络化多智能体系统的共识与合作

在所有参与者之间提供快速协议和团队合作的算法通过自组织网络系统实现有效的任务执行。By Reza Olfati-Saber, Member IEEE, J. Alex Fax, and Richard M. Murray, Fellow IEEE小于 翻译摘要&#xff1a;本文提供了一个理论框架&#xff0c;用于分析多智能体网络系统的共识算法…

Linux文件与目录的查看:ls

前言 ls作为我们在Linux系统中最常用的命令&#xff0c;因为我们常常需要去知道文件或是目录的相关信息&#xff0c;但我们Linux的文件所记录的信息实在是太多了&#xff0c;ls也没有需要全部都列出来&#xff0c;所以&#xff0c;当我们执行ls命令时&#xff0c;默认显示的只…

【数据结构】基础:二叉搜索树

【数据结构】基础&#xff1a;二叉搜索树 摘要&#xff1a;本文为二叉树的进阶&#xff0c;主要介绍其概念与基本实现&#xff08;递归与非递归&#xff09;&#xff0c;再介绍其应用&#xff0c;主要介绍内容为KV模型。最后为简单的性能分析。 文章目录【数据结构】基础&#…

【数据结构】1.1 数据结构的研究内容

文章目录数据结构的研究内容数据结构研究的内容小结数据结构的研究内容 早期&#xff0c;计算机主要用于数值计算: 首先&#xff0c;分析问题、提取操作对象&#xff0c;然后&#xff0c;找出操作对象之间的关系&#xff0c;用数学语言加以描述&#xff0c;建立相应数学方程。…

Java日志门面技术 SLF4J

文章目录背景SLF4J概述切换日志框架实际应用配合自身简单日志实现(slf4j-simple)配置logback日志实现配置Log4J日志实现(需适配器)配置JUL日志实现(需适配器)添加slf4j-nop依赖(日志开关)桥接旧的日志实现框架背景 随着系统开发的进行&#xff0c;可能会更新不同的日志框架&am…

TF数据流图图与TensorBoard

2.1 TF数据流图 学习目标 目标 说明TensorFlow的数据流图结构应用 无内容预览 2.1.1 案例&#xff1a;TensorFlow实现一个加法运算 1 代码2 TensorFlow结构分析2.1.2 数据流图介绍 2.1.1 案例&#xff1a;TensorFlow实现一个加法运算 2.1.1.1 代码 def tensorflow_demo():&…

CMMI对企业有什么价值,如何高效落地?

1、获得权威认证 CMMI是全球性软件与系统工程行业的唯一权威认证&#xff0c;是对企业软件研发与能力服务的认可。 CMMI企业价值 CoCode项目管理全面支持CMMI3-5级高效落地​ 2、降本增效&#xff0c;提高企业能力。 CMMI对软件开发过程进行规范化梳理&#xff0c;保证软…

虚拟机ubuntu系统内存满,无法进入桌面,扩展内存

1、 关闭虚拟机&#xff0c;在虚拟机设置中将原先20GB扩展到30GB 注意&#xff1a;有快照需要删除快照后才能扩展 2、命令行进入ubuntu 内存满了&#xff0c;无法进入Ubuntu图形界面 按下ctrlaltf2~f6组合键 输入用户名和密码进入命令行模式 3、删除一些东西 删除回收站…

vuex的modules和辅助函数

一、回顾&#xff1a;vuex状态管理器1、版本问题&#xff1a;vue2对应的是vuex3&#xff1b;vue3对应的vuex42、vuex作用&#xff1a;每个vuex中都有一个Store(仓库)&#xff0c;用于管理vue项目中用到的状态变量&#xff08;属性&#xff09;。vuex维护的是一个单一的状态树vu…