stm32入门-----硬件I2C读写MPU6050

 目录

前言

 一、stm32中I2C库函数介绍(stm32f10x_i2c.h)

1.初始化

2.使能操作

3.生成起始位和结束位标志

4.发送I2C从机地址

5.发送数据和接收数据

6.发送应答位

7.状态检测

二、硬件I2C读取MPU6050

1.电路连线图

2.主要工程文件 

3.MPU6050.c代码剖析

(1)检测步骤超时操作

(2)指定地址写

(3)指定地址读

(4)初始化配置

(5)获取MPU6050寄存器数据

4.主函数代码


前言

        上一期讲了硬件I2C的相关基本内容(链接stm32入门-----硬件I2C外设-CSDN博客),本期我们就来学习硬件I2C读写MPU6050的项目实操,在前面我们试过了用软件I2C来去读写MPU6050的操作,这里我们可以去对比看看硬件跟软件操作上有什么不同以及硬件上又有哪方面比软件要强。(视频:STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili)

本期项目代码我已上传至百度网盘,可自行下载
链接:https://pan.baidu.com/s/1W_2qnkWsUkOBzRjhkJhRVg?pwd=0721 
提取码:0721 

 一、stm32中I2C库函数介绍(stm32f10x_i2c.h)

下面这些是关于I2C的库函数,这里我会挑选最常见的以及本期要用到的来去进行详细讲解。

1.初始化

在学过前面这么多结构体初始化的函数,对于结构体的初始化我们已经再属性不过了,下面是I2C外设的结构体初始化的函数。

void I2C_DeInit(I2C_TypeDef* I2Cx);//恢复缺省配置
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);//定义好结构体后初始化
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);//使用默认结构体初始化

一般情况我们都是自己去定义配置结构体再初始化的,下面我们看一个定义好结构体初始化的示例:

I2C_InitTypeDef I2C_initstruct;I2C_initstruct.I2C_Mode = I2C_Mode_I2C; //选择模式,这里选定使用I2C模式I2C_initstruct.I2C_ClockSpeed = 100000; //选择时钟的频率,不得大于400kHzI2C_initstruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比选择,低电平:高电平,如果当前是标准速度的话,这个是没用的的,如果在快速时钟的时候,这个才会起作用I2C_initstruct.I2C_Ack = I2C_Ack_Enable; //选择是否给应答I2C_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//stm32作为从机的时候的响应地址位数I2C_initstruct.I2C_OwnAddress1 = 0x01;   //stm32作为从机的时候地址,我们这里是主机,所以这里随便设一个就行了I2C_Init(I2C2, &I2C_initstruct);

2.使能操作

我们本期不需要用DMA到使能,所以这里就不过多讲解。

void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);//I2C使能
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState); //开启I2C的DMA使能
void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

3.生成起始位和结束位标志

void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);//产生起始位标志
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);//产生结束位标志

手册解释如下:

4.发送I2C从机地址

 下面这个函数其实就是前面学习软件I2C的“点名”操作,硬件也是一样的,同样都是需要进行点名指定的I2C从机来进行通讯。如果有多个从机,主机会执行下面这个函数后会给每一个从机发送Address的数据,然后从机接收到了后就对比自己的IP数据,如果一样的话那么就开始跟主机通讯,其他从机保持沉默。

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);

5.发送数据和接收数据

下面这个是发送数据:

void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);

下面可以看到把数据放入到数据寄存器DR的操作后,然后剩下就是进入到发送数据的流程。 

下面这个是接受数据:

uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);

我们可以看到这个函数的返回值是DR寄存器里面的数据。 

6.发送应答位

下面这个函数是用来发送应答位的,当主机接收到了数据之后会向从机发送应答情况,如果应答位是ENABLE表示接收完成返回一个应答反之就是无应答返回 ,手册解释如下

void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)

7.状态检测

下面这个函数是用来检测每次操作一个步骤之后的状态的,比如发送了一个字节后的数据,然后就会进入一个EVx的状态,这里就需要去执行这个状态是否完成,然后再执行下一步,这是一种缓冲机制以保证数据收发的准确性。在上一期我们也是详细讲解过了这个过程了的。

ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)

下面是这个函数的相关参数: 

二、硬件I2C读取MPU6050

实验现象如下,其实跟前面软件I2C读取MPU6050现象是一样的,只是方法不同。(软件I2C读取MPU6050链接:stm32入门-----软件I2C读写MPU6050-CSDN博客)

1.电路连线图

2.主要工程文件 

主要工程文件如下,这里我们就没有像软件那部分一样需要建立一个MyI2C的文件来去执行收发数据的底层,这里我们是使用硬件外设配置库函数来去实现I2C通讯的,底层是由硬件来自动执行的,所以就不需要MyI2C这个文件了。

其中MPU6050.c文件是用来配置I2C外设以及MPU6050相关模块的文件,MPU6050_reg.h文件是存放MPU6050相关寄存器数据的文件。

 MPU6050_reg.h文件数据如下:

#ifndef __MPU6050_REG_h
#define __MPU6050_REG_h//这里存放的是MPU6050的寄存器地址
#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 // !__MPU6050_REG_h

这里我们主要去讲解MPU6050.c这个文件里面的内容,这个是配置I2C外设的主要文件。

3.MPU6050.c代码剖析

(1)检测步骤超时操作

在进入到检测状态的函数的时候,难免会出现意外超时的情况,这里我们就需要去对这个bug进行处理,比如如果超时的情况就放弃这个字节读取或写入的操作。

//检测事件后的超时操作
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) {uint32_t time_out = 100000;while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS) {time_out--;if (!time_out) {break;} }
}
(2)指定地址写

代码是对应下面这个序列图进行写的,序列图跟代码的步骤是一样的,我们这里使用的是7位。

//指定地址写
void MPU6050_writereg(uint8_t regaddress, uint8_t data) {//开启I2C发送模式I2C_GenerateSTART(I2C2, ENABLE);MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//监测EV5事件,返回值有SUCCESS和ERROR//发送地址,点名I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);//I2C_SendData()函数也是用来发送的,不过I2C_Send7bitAddress这个可以选择7位的发送和接收地址位两种模式MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//监测EV6事件,返回值有SUCCESS和ERROR//选择寄存器地址I2C_SendData(I2C2, regaddress); //选择从机的寄存器地址MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);//监测EV8事件,返回值有SUCCESS和ERROR//发送数据I2C_SendData(I2C2, data); //选择从机的寄存器地址MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);//监测EV8_2事件表示结束,返回值有SUCCESS和ERRORI2C_GenerateSTOP(I2C2, ENABLE);
}
(3)指定地址读

//指定地址读
uint8_t MPU6050_readreg(uint8_t regaddress) {uint8_t result;//这里指定地址//开启I2C发送模式I2C_GenerateSTART(I2C2, ENABLE);MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//监测EV5事件,返回值有SUCCESS和ERROR//选择发送地址,点名I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);//I2C_Send7bitAddress这个可以选择7位的发送和接收地址位两种模式,选择方向和从机地址MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//监测EV6事件,返回值有SUCCESS和ERROR//选择寄存器地址I2C_SendData(I2C2, regaddress); //选择从机的寄存器地址MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);//监测EV8事件,返回值有SUCCESS和ERROR//这里就开始读取这个寄存器的数据//重新开启I2C_GenerateSTART(I2C2, ENABLE);MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//监测EV5事件,返回值有SUCCESS和ERROR//发送地址,点名I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);//这里选择接收的方向MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//监测EV6事件,返回值有SUCCESS和ERROR//如果是读取多个字节的时候,那读取最后一个字节之前在这里需要去先去给应答置0,提前终止接收stop置1//如果读取一个字节的时候,那么要在EV6之后在这里应答ack置0,stop置1//这里提前设置的终止stop的时候不会影响数据的收到,回等待最后一个字节数据接收完成之后才去执行终止I2C_AcknowledgeConfig(I2C2, DISABLE);I2C_GenerateSTOP(I2C2, ENABLE);MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);//监测EV6事件,返回值有SUCCESS和ERROR//读取DRresult = I2C_ReceiveData(I2C2);I2C_AcknowledgeConfig(I2C2, ENABLE);return result;
}
(4)初始化配置
//初始化
void MPU6050_init() {// I2C_init();//1.开启时钟,GPIO和I2C的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 2.初始化引脚GPIO_InitTypeDef GPIO_initstruct;GPIO_initstruct.GPIO_Mode=GPIO_Mode_AF_OD; //选择使用复用开漏输出模式 GPIO_initstruct.GPIO_Pin=GPIO_Pin_11 | GPIO_Pin_10;GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_initstruct);// 3.配置初始化I2C外设I2C_InitTypeDef I2C_initstruct;I2C_initstruct.I2C_Mode = I2C_Mode_I2C; //选择模式,这里选定使用I2C模式I2C_initstruct.I2C_ClockSpeed = 100000; //选择时钟的频率,不得大于400kHzI2C_initstruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比选择,低电平:高电平,如果当前是标准速度的话,这个是没用的的,如果在快速时钟的时候,这个才会起作用I2C_initstruct.I2C_Ack = I2C_Ack_Enable; //选择是否给应答I2C_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//stm32作为从机的时候的响应地址位数I2C_initstruct.I2C_OwnAddress1 = 0x01;   //stm32作为从机的时候地址,我们这里是主机,所以这里随便设一个就行了I2C_Init(I2C2, &I2C_initstruct);MPU6050_writereg(MPU6050_PWR_MGMT_1, 0x01); //电源管理器1MPU6050_writereg(MPU6050_PWR_MGMT_2, 0x00); //电源管理器2MPU6050_writereg(MPU6050_SMPLRT_DIV, 0x09); //分频器MPU6050_writereg(MPU6050_CONFIG, 0x06); //配置寄存器MPU6050_writereg(MPU6050_GYRO_CONFIG, 0x18); //陀螺仪配置寄存器MPU6050_writereg(MPU6050_ACCEL_CONFIG, 0x18);//加速度计配置寄存器
}
(5)获取MPU6050寄存器数据
//获取当前的ID号,也就是MPU6050的I2C地址
uint8_t MPU6050_getID() {return MPU6050_readreg(MPU6050_WHO_AM_I);
}//获取MPU6050转换出加速度和角速度的值
void MPU6050_getdata(int16_t* accX, int16_t* accY, int16_t* accZ,int16_t* gyroX, int16_t* gyroY, int16_t* gyroZ)
{uint16_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;
}

4.主函数代码

这部分其实跟软件I2C读写MPU6050的是一样的。

#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);}
}

以上就是本期的全部内容了,我们下次见!

今日壁纸:

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

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

相关文章

虚拟机(CentOS7)安装jenkins

centos7安装jenkins 前提条件&#xff0c;安装jdk与maven 1、JDK17安装 # 进入系统管理员 sudo root # 进入对应文件夹下 cd /usr/local # 下载jdk17 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm # rpm命令安装下载的jdk17 rpm -ivh jdk-17_li…

GPU爆显存 | Windows下杀死GPU进程释放显存

文章目录 0 问题引入1 解决方案 0 问题引入 深度学习的时候&#xff0c;用CUDA加速训练了&#xff0c;但是进程没有完全结束&#xff0c;再跑的时候爆显存了。 1 解决方案 查看当前的GPU进程 nvidia-smi通过如下命令来杀死指定的进程。 taskkill /PID PID号 /F //例如&am…

Netty一

Netty Netty介绍 Netty应用场景 I/O模型 阻塞IO 同步非阻塞IO 异步非阻塞IO BIO NIO AIO对比 Netty线程模型 Reactor模式 单Reactor单线程 单Reactor多线程 主从Reactor多线程 Netty模型 异步模型 Future-Listener机制 TCP粘包拆包基本介绍 Netty内存使用 Netty内存池化 Netty…

Spring中使用Async进行异步功能开发实战-以大文件上传为例

目录 前言 一、场景再现 1、Event的同步机制 二、性能优化 1、异步支持配置 2、自定义处理线程池扩展 3、将线程池配置类绑定到异步方法 三、总结 前言 在之前的博客中&#xff0c;曾将讲了在SpringBoot中如何使用Event来进行大文件上传的解耦&#xff0c;原文地址&…

Java-变量,运算符,输入与输出

目录 一&#xff0c;语法基础 1.基本Java程序 2.语法基础 2.1 变量 2.2 常量限制(fiinal)类比C中的const 2.3 类型转化 2.4 运算符 2.5 表达式 2.5 输入与输出 2.5.1 输入 2.5.2 输出 一&#xff0c;语法基础 1.基本Java程序 public class Main{public static void…

C#使用NPOI进行Excel和Word文件处理(一)

文章目录 前言文件大小性能NPOI 的优势示例代码性能优化建议总结Github 地址链接导出效果 前言 NPOI 是一个非常流行的用于在 .NET 环境中操作 Office 文件&#xff08;包括 Excel 文件&#xff09;的开源库。它的功能非常强大&#xff0c;但性能和文件大小问题可能因具体的使…

虚拟机如何使用pxe服务实现自动安装系统

一、前提 服务机为rhel7.9 因为我们需要虚拟机为服务器来给要安装系统的虚拟机分配IP 所以要先将VMWare的NAT模式的DHCP自动分配取消&#xff0c;如图&#xff1a; yum install httpd -y systemctl enable --now httpd 二、基于HTTP协议的PXE服务器 1、首先需要进入图形化…

Redis-管道

面试题 如何优化频繁命令往返造成的性能瓶颈 Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。一个请求会遵循以下步骤: 1 客户端向服务端发送命令分四步(发送命令-命令排队一命令执行-返回结果)&#xff0c;并监听Socket返回&#xff0c;通常以阻塞模式等待服…

How does age change how you learn?(2)年龄如何影响学习能力?(二)

Do different people experience decline differently? 不同人经历的认知衰退会有不同吗? Do all people experience cognitive decline uniformly?Or do some people’s minds slip while others stay sharp much longer? 所有人经历的认知衰退都是一样的吗?还是有些人…

Linux--应用层协议HTTP

HTTP协议 HTTP协议&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最为广泛的一种网络协议&#xff0c;它基于TCP/IP通信协议来传送数据&#xff0c;规定了浏览器与服务器之间数据传输的规则&#xff0c;确保数据能够在网络源头…

JavaEE 第1节 认识多线程

本节目标&#xff08;全是重点&#xff0c;都必须掌握&#xff09; 1、了解什么是线程、多线程、进程以及他们之间的关系 2、了解多线程的优势以及各种特性 3、用Java掌握多种创建线程的方法 一、线程、多线程、进程 1、概念 1.基本概念 这三个名词的概念可以用一个餐馆…

安卓自定义控件

文章目录 引入布局创建自定义控件 引入布局 首先创建一个项目&#xff0c;创建一个空的活动。然后右键单击res/layout创建一个Layout Resource File文件&#xff0c;取名title.xml。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmln…

【Linux】win 环境下进行 linux开发

文章目录 IDE 安装Python开发创建一个新项目安装 Python、pip 和 venv创建虚拟环境&#xff08;建议&#xff09;运行Python 参考文章 想要win 环境下进行 linux开发&#xff0c;需要依赖于wsl。wsl安装可参考上篇文章 【Linux】wsl win安装Linux环境 这里主要介绍在 linux下…

《学会 SpringMVC 系列 · 剖析入参处理》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【大模型系列】Video-LLaVA(2023.12)

Paper&#xff1a;https://arxiv.org/pdf/2311.10122v2Github&#xff1a;https://github.com/PKU-YuanGroup/Video-LLaVAHuggingface&#xff1a;https://huggingface.co/spaces/LanguageBind/Video-LLaVAAuthor&#xff1a;Bin Lin et al. 北大袁粒团队 文章目录 1 Video-LLa…

各地级市能源消费总量、夜间灯光值数据(2000-2022年)

全国各地级市能源消费总量、夜间灯光值数据&#xff08;2000-2022年&#xff09; 数据年限&#xff1a;2000-2022年 数据格式&#xff1a;excel 数据内容&#xff1a;337个地级市能源消费总量、夜间灯光值数据&#xff0c;包括城市、省份、年份、夜间灯光值&#xff08;总和&am…

基于pytorch的steam游戏评分的线性回归问题分析

前言 相信已经暑假一个月的大家肯定并不陌生上面这个学习软件()&#xff0c;面对琳琅满目的游戏总是让人不知道挑选什么&#xff0c;这时候一个游戏的评分往往便成为了一个玩家选择下载的原因&#xff0c;那么今天我们就来研究研究&#xff0c;steam上一个游戏的种种数据&…

【window10/window11】解决任务管理器有进程无法强制结束情况

以管理员身份启动控制台窗体&#xff0c;然后从任务管理器中查询到你要结束的进程名&#xff0c;然后运行以下命令&#xff08;UniAccessAgent.exe替换成你要结束的进程&#xff09;&#xff1a; wmic process where nameUniAccessAgent.exe delete 此方法可以解决在任务管理…

快速体验LLaMA-Factory 私有化部署和高效微调Llama3模型(曙光超算互联网平台异构加速卡DCU)

序言 本文以 LLaMA-Factory 为例&#xff0c;在超算互联网平台SCNet上使用异构加速卡AI 显存64GB PCIE&#xff0c;私有化部署Llama3模型&#xff0c;并对 Llama3-8B-Instruct 模型进行 LoRA 微调、推理和合并。 快速体验基础版本&#xff0c;请参考另一篇博客&#xff1a;快…

Animate软件基础:在时间轴中标识动画

FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&#xff1a;Animate教程及作品源文件https://zhuanlan.zhihu.co…