STM32学习笔记之存储器映射(原理篇)
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨
📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】
📢:文章若有幸对你有帮助,可点赞 👍 收藏 ⭐不迷路🙉
📢:内容若有错误,敬请留言 📝指正!原创文,转载注明出处
文章目录
- 什么是存储器映射呢?
- 为什么叫存储器映射,而不是寄存器映射呢?
- 存储器映射实现
- 什么是寄存器映射?
- 寄存器映射实现
- 为什么要设置存储器映射?
- stm32单片机地址总线访问大小是4G,是不是意味着内存大小也是4G?
什么是存储器映射呢?
存储器本身不具备地址,所以把芯片内核所预先设定好的地址分配给寄存器,就是存储器映射。因为stm32的地址线是32位,也就是2的32次方,正好是对应4G的虚拟存储空间。把内核厂商(也就是ARM公司)定义的这个虚拟空间与芯片厂商(这里是ST)芯片内部外设进行对应,也就是给存储器分配地址,即存储器映射。4个G的地址这么大,用不完没关系,可以保留。
为什么叫存储器映射,而不是寄存器映射呢?
在 STM32 单片机中,“存储器映射” 是指将不同的物理存储区域(如内部闪存、SRAM、外设寄存器等)和一些逻辑存储区域(如系统保留区域等)按照一定的规则,映射到一个统一的地址空间中,使得 CPU 可以通过访问这个统一地址空间中的不同地址来访问不同的物理或逻辑存储区域。因此存储器映射包含寄存器映射。
存储器映射实现
请查看存储器映射关系在代码中是如何体现的。下图是我项目中的 stm32f4xx.h 文件的部分代码。
#define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH(up to 1 MB) base address in the alias region */
#define CCMDATARAM_BASE ((uint32_t)0x10000000) /*!< CCM(core coupled memory) data RAM(64 KB) base address in the alias region */
#define SRAM1_BASE ((uint32_t)0x20000000) /*!< SRAM1(112 KB) base address in the alias region */
#define SRAM2_BASE ((uint32_t)0x2001C000) /*!< SRAM2(16 KB) base address in the alias region */
#define SRAM3_BASE ((uint32_t)0x20020000) /*!< SRAM3(64 KB) base address in the alias region */
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define BKPSRAM_BASE ((uint32_t)0x40024000) /*!< Backup SRAM(4 KB) base address in the alias region */#if defined (STM32F40_41xxx)
#define FSMC_R_BASE ((uint32_t)0xA0000000) /*!< FSMC registers base address */
#endif /* STM32F40_41xxx */#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
#define FMC_R_BASE ((uint32_t)0xA0000000) /*!< FMC registers base address */
#endif /* STM32F427_437xx || STM32F429_439xx */#define CCMDATARAM_BB_BASE ((uint32_t)0x12000000) /*!< CCM(core coupled memory) data RAM(64 KB) base address in the bit-band region */
#define SRAM1_BB_BASE ((uint32_t)0x22000000) /*!< SRAM1(112 KB) base address in the bit-band region */
#define SRAM2_BB_BASE ((uint32_t)0x2201C000) /*!< SRAM2(16 KB) base address in the bit-band region */
#define SRAM3_BB_BASE ((uint32_t)0x22400000) /*!< SRAM3(64 KB) base address in the bit-band region */
#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */
#define BKPSRAM_BB_BASE ((uint32_t)0x42024000) /*!< Backup SRAM(4 KB) base address in the bit-band region
/*!< Peripheral memory map */
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000)/*!< APB1 peripherals */
#define TIM2_BASE (APB1PERIPH_BASE + 0x0000)
#define TIM3_BASE (APB1PERIPH_BASE + 0x0400)
#define TIM4_BASE (APB1PERIPH_BASE + 0x0800)
#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00)
#define TIM6_BASE (APB1PERIPH_BASE + 0x1000)
#define TIM7_BASE (APB1PERIPH_BASE + 0x1400)
#define TIM12_BASE (APB1PERIPH_BASE + 0x1800)
#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00)
#define TIM14_BASE (APB1PERIPH_BASE + 0x2000)
#define RTC_BASE (APB1PERIPH_BASE + 0x2800)
#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00)
#define IWDG_BASE (APB1PERIPH_BASE + 0x3000)
#define I2S2ext_BASE (APB1PERIPH_BASE + 0x3400)
#define SPI2_BASE (APB1PERIPH_BASE + 0x3800)
#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00)
#define I2S3ext_BASE (APB1PERIPH_BASE + 0x4000)
什么是寄存器映射?
在存储器Block2这块区域,设计的是片上外设,它们以4个字节为一个单元,共32bit,那么每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过C语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这是我们可以根据每个单元的功能不同,以功能为名给这个存储单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
寄存器映射实现
第一步:宏定义GPIO 口的基地址,AHB1PERIPH_BASE 依次累加 0x400的地址偏移量,就得到GPIOA~GPIOK的基地址。
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)
#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400)
#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800)
#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)
#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000)
#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400)
#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800)
#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00)
#define GPIOI_BASE (AHB1PERIPH_BASE + 0x2000)
#define GPIOJ_BASE (AHB1PERIPH_BASE + 0x2400)
#define GPIOK_BASE (AHB1PERIPH_BASE + 0x2800)
第二步:把这个GPIO的基地址通过加上(GPIO_TypeDef *)这步骚操作,来把地址强转成具有GPIO_TypeDef 性质的指针变量,并且用#define进行宏定义,实现取了个别名的效果。这就是寄存器的映射。
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)
#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE)
#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE)
#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE)
GPIO_TypeDef结构体的声明:
typedef struct
{__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */__IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */__IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;
为什么要设置存储器映射?
之所以这样做,有以下几个原因:
- 统一访问接口:CPU通过地址总线访问内存和外设等不同部件时,采用统一的存储器映射方式,就可以使用相同的指令和操作来进行数据的读写。例如,无论是访问内部SRAM中的数据,还是向外设寄存器写入控制命令,都可以通过对相应地址的操作来完成,无需为不同的部件设计不同的访问指令和接口,简化了硬件设计和软件开发的复杂度。
- 灵活的资源分配:存储器映射可以根据不同的应用需求,灵活地将地址空间分配给各种不同的存储介质和外设。例如,在设计一个具体的产品时,可以根据实际需要,将一部分地址空间分配给外部扩展的大容量Flash存储器用于存储程序和数据,将另一部分地址空间分配给特定的外设,如网络控制器、SD卡控制器等,使系统能够高效地利用各种资源,满足不同的功能需求。
- 方便系统扩展:当需要对系统进行扩展时,无论是增加新的存储设备还是添加新的外设,都可以通过合理地分配存储器映射地址来实现。新的设备可以很容易地集成到现有的系统中,只需将其映射到未使用的地址空间,并编写相应的驱动程序来访问这些地址即可,而无需对整个系统的架构进行大规模的修改。
stm32单片机地址总线访问大小是4G,是不是意味着内存大小也是4G?
STM32单片机地址总线访问大小是4G,但这并不意味着其内存大小就是4G。
地址总线的宽度决定了CPU可以访问的地址空间范围。STM32单片机基于ARM Cortex - M内核,其具有32位地址总线,所以理论上可访问的地址空间为(2^{32})= 4G字节。然而,这4G的地址空间是包括了多个部分的,不仅仅是内存(RAM和ROM),还包括以下部分:
- 片上外设寄存器空间:用于访问各种片上外设,如GPIO、USART、SPI等外设的控制寄存器。每个外设都有其特定的地址范围,通过地址总线来访问这些寄存器以实现对外设的控制和数据传输。
- 外部设备扩展空间:如果单片机扩展了外部的Flash、RAM、FPGA等设备,这些设备也会占用一定的地址空间,与片上资源共同构成整个可寻址的4G空间。
- 系统保留区域:一些地址范围可能被保留用于特定的系统功能或未来扩展,并不对应实际的物理存储或外设。
实际上,STM32单片机内部的内存(如SRAM和Flash)容量通常远小于4G。不同型号的STM32其内部SRAM一般在几十KB到几百KB之间,内部Flash存储器一般在几十KB到几MB之间。
相关文章:
STM32学习笔记之存储器映射(原理篇)
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
探索PyMOL新插件NRGSuite-Qt:全面提升分子对接、结合位点预测与动力学模拟的研究效率
随着分子建模和计算生物学的快速发展,分子对接(Molecular Docking)、结合位点预测、相互作用分析以及动力学研究等领域的工具越来越重要。这些工具不仅帮助研究人员理解分子间的相互作用机制,还能加速药物设计和优化过程。NRGSuit…...
c#在work线程中怎样更新UI控件
最近笔者调试修改项目,碰到了c#在work线程中怎样更新UI控件中的场景,简单总结了下,主要有两个方法: 方法1:通过System.Windows.Application.Current.Dispatcher.Invoke来更新UI控件 System.Windows.Application.Curre…...
DeepSeek、Grok 与 ChatGPT 4.5:新一代大模型架构与推理能力深度解析
近年来,大语言模型(LLM)领域发展迅猛,DeepSeek、Grok 以及 OpenAI 最新发布的 ChatGPT 4.5 都是该领域的代表性产品。本文将从架构设计、推理能力、训练策略等方面,对三者进行技术对比,探讨其优势与潜在的应…...
从零基础到 Java 网站项目开发学习规划
在数字化时代,Java 凭借其卓越的跨平台性、强大的功能和丰富的类库,成为开发各类网站的主流编程语言。对于想要踏入 Java 网站开发领域的初学者而言,一份系统、科学的学习规划至关重要。它不仅能帮助我们有条不紊地掌握知识和技能,…...
Unity Shader 学习17:合批渲染
一、基础概念 合批主要是针对这三个概念进行优化减少: ① SetPass Call:一次渲染状态切换,也就是每次切换 材质/Pass 时,就会触发一次SetPass Call ② Draw Call:cpu 调用一次 gpu 绘制函数 ③ Batch:表示…...
【JavaSE】抽象类和接口
【JavaSE】抽象类和接口 前言:补充知识 —— 利用类和对象,交换两个数字 一、抽象类1.1 抽象类是什么?1.2 抽象类特点1.3 抽象类举例1.4 抽象类作用 二、接口2.1 接口是什么?2.2 接口的特性2.3 接口的使用规则2.4 类可以实现多个接…...
嵌入式单片机程序的映像文件解读
映像文件类型 单片机下载程序的映像文件是包含了可执行代码、数据等信息,用于将程序烧录到单片机中的文件。常见的映像文件种类如下: 十六进制文件(Hex 文件) 格式特点:Hex 文件是一种文本格式的文件,以 ASCII 字符形式存储数据。它由一系列的记录组成,每条记录包含一个…...
在 Linux(Ubuntu / CentOS 7)上快速搭建我的世界 MineCraft 服务器,并实现远程联机,详细教程
Linux 部署 MineCraft 服务器 详细教程(丐版,无需云服务器) 一、虚拟机 Ubuntu 部署二、下载 Minecraft 服务端三、安装 JRE 21四、安装 MCS manager 面板五、搭建服务器六、本地测试连接七、下载樱花,实现内网穿透,邀…...
STL之string
1.为什么学习string类 1.1 C语言中的字符串 C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且…...
cJSON-轻量级 C 语言 JSON 解析库的使用(一)
文章目录 cJSON:轻量级 C 语言 JSON 解析库的使用前言一、cJSON 简介核心特点: 二、核心数据结构解析三、深入解析 API 设计1. 解析 JSON2. 访问数据3. 构建 JSON 四、内存管理策略五、高级应用技巧1. 引用系统2. 批量操作3. 原地修改 六、性能优化技巧1…...
用Python和Stable Diffusion生成AI动画:从图像到视频的全流程指南
引言 本文将演示如何通过Python代码实现基于文本提示的AI动画生成。我们将使用Stable Diffusion生成连贯图像帧,结合OpenCV合成视频,最终实现一个可自定义的动画生成 pipeline。 一、环境准备 1. 依赖安装 # 安装核心库 pip install diffusers transformers torch numpy …...
C++ 继承:面向对象编程的核心概念(二)
文章目录 5. 继承与友元6. 继承与静态成员7. 多继承及其菱形继承问题7.1 不同的继承方式7.2 虚继承 8. 继承和组合9. 总结 书接上回:C 继承:面向对象编程的核心概念(一) 5. 继承与友元 友元关系不能继承,也就是说基类友元不能访问…...
Chaos Mesh 混沌工程平台介绍、安装及使用指南
Chaos Mesh 混沌工程平台介绍、安装及使用指南 一、Chaos Mesh 简介 Chaos Mesh 是 PingCAP 开源的云原生混沌工程平台,支持在 Kubernetes 环境中模拟各种故障场景,帮助提升系统的容错性和可恢复性。 核心特性 丰富的故障类型: 资源类&…...
每天五分钟深度学习框架PyTorch:梯度裁剪解决RNN梯度爆炸的问题
本文重点 在循环神经网络训练的过程中,有时候很容易出现梯度爆炸的情况,如果出现这种问题,我们应该怎么办?本文先来分析一下为什么会出现这种情况,然后我们在给出解决方案 梯度爆炸的原因 我们从RNN训练的反向传播算法入手,当我们使用BPTT算法训练RNN的时候,它的公式…...
批量删除 PDF 中的所有图片、所有二维码图片以及指定的某张图片
PDF 文档中我们可以插入图片、文字等多种类型的资源。在某些场景下,可能我们需要删除 PDF 文档中的图片,有可能是需要删除所有的图片,也有可能是删除固定的某些图片。那碰到这种情况,我们应该怎么处理呢?今天就给大家介…...
力扣HOT100之普通数组:53. 最大子数组和
这道题目我用贪心做的,感觉用贪心的思路比较简单,以后要是面试碰到这道题就直接用贪心好了,这道题用贪心的核心思想就是不断将数组元素i加入总和sum,如果sum比当前维护的最大值result更大,说明当前遍历到的i是正数&…...
【Qt】C++前向声明与Qt信号与槽的区别
相同点:二者都可以解决头文件相互包含的问题 一、C 前向声明 概念:前向声明是在代码里仅仅声明一个类、函数或者变量,而不给出其完整定义。例如class MyClass; 就是对 MyClass 类的前向声明。 作用:主要是为了降低编译依赖&…...
SQL-木马植入、报错注入及其他
一、读写权限确认 show global variables like %secure%; 查看mysql全局变量的配置,当输入以上命令时,结果 secure_file_priv 空的时候,任意读写 secure_file_priv 某个路径的时候,只能在规定的那个路径下读写 secure_file_pri…...
基于 PHP 内置类及函数的免杀 WebShell
前言 PHP 作为广泛使用的服务端语言,其灵活的内置类(如 DOMDocument)和文件操作机制(.ini、.inc 的自动加载),为攻击者提供了天然的隐蔽通道。通过 动态函数拼接、反射调用、加密混淆 和 伪命名空间 等手法…...
主键id设计
主键自增id 🌱 1. 自增 ID(Auto Increment ID) ✅ 特点: • 数据库自带(MySQL, PostgreSQL 都支持) • 简单易用,可读性强 • 一般作为主键自带聚簇索引(主键就是物理存储顺序&…...
文件上传绕过的小点总结(6)
14.文件上传(文件包含漏洞)二次渲染 很多服务器为了防止代码嵌入图片,通常会将上传的图片进行重新生成处理,包括文件格式转换等等,嵌入的恶意代码很容易被改掉。于是产生了二次渲染,二次渲染的原理就是找到…...
传统应用容器化迁移实践
背景介绍:从传统部署到容器化迁移的必要性 在过去的运维工作中,某企业一直依赖于传统的物理机和虚拟机部署方式。然而,随着业务的快速发展和应用规模的不断扩大,传统部署方式的局限性逐渐显现: 资源利用率低…...
混境之地1
问题描述 小蓝有一天误入了一个混境之地。 好消息是:他误打误撞拿到了一张地图,并从中获取到以下信息: 混境之地的大小为 n⋅mn⋅m,其中 # 表示这个位置很危险,无法通行,. 表示道路,可以通行。他…...
LLM 加速技术有哪些
LLM 加速技术有哪些 目录 LLM 加速技术有哪些量化(Quantization)基本原理举例剪枝(Pruning)基本原理举例动态Shape(Dynamic Shape)基本原理举例算子融合(Operator Fusion)基本原理举例量化(Quantization) 基本原理 量化是指将模型中连续取值(如32位浮点数)的参数…...
CPP从入门到入土之类和对象Ⅲ
拷贝构造函数 拷贝构造函数是一个已经存在的对象去初始化一个新的对象时,调用的函数 例如: 假设我有一个盒子,里面装了一个苹果 拷贝构造函数的特点 拷贝构造函数是构造函数的一个重载拷贝构造函数的第一个参数必须是类类型对象的引用,例如…...
安全上网沙箱:多方面解决政企私的上网问题
在数字化的浪潮中,网络已成为我们工作与生活不可或缺的一部分。然而,网络的便捷也伴随着诸多安全隐患,尤其是对于企业、个人以及政企机构而言,安全上外网成为了至关重要的课题。 隔离保护:构建安全堡垒 沙箱技术在内网…...
空转 | GetAssayData doesn‘t work for multiple layers in v5 assay.
问题分析 当我分析多个样本的时候,而我的seurat又是v5时,通常就会出现这样的报错。 错误的原因有两个: 一个是参数名有slot变成layer 一个是GetAssayData 不是自动合并多个layers,而是选择保留。 那么如果我们想合并多个样本&…...
26、web前端开发之CSS3(三)
5. 文本(Text) CSS3大大增强了对文本样式和排版的控制,使得网页设计更加灵活和多样化。本讲详细介绍CSS3中常用的文本相关属性,包括文本对齐、字体大小、行高、字母间距、单词拆分、溢出隐藏等,帮助开发者更好地控制和…...
第 8 章:使用更好的库_《C++性能优化指南》_notes
使用更好的库 第八章核心知识点解析编译与测试建议总结优化原则重点内容:第一部分:多选题(10题)第二部分:设计题答案与解析多选题答案:设计题答案示例(部分): 测试用例设…...
【面试八股】:常见的锁策略
常见的锁策略 synchronized (标准库的锁不够你用了)锁策略和 Java 不强相关,其他语言涉及到锁,也有这样的锁策略。 1. 悲观锁,乐观锁(描述的加锁时遇到的场景) 悲观锁:预测接下来…...
Apache Iceberg 解析,一文了解Iceberg定义、应用及未来发展
什么是 Iceberg? Apache Iceberg 是一种开源的 表格式(Table Format) ,专为超大规模数据分析场景设计,通过标准化数据存储规范与访问协议,解决了传统数据湖在元数据管理、事务控制、查询性能等方面的核心痛…...
Ubuntu 优化启动时间优化
优化 Ubuntu 20.04 的启动时间可以从多个方面入手,以下是详细的步骤和建议: 一、分析启动耗时 首先检查系统启动各阶段的耗时: systemd-analyze time # 查看整体启动时间 systemd-analyze blame # 列出各服务/进程的启动耗时 …...
【Git 常用指令速查表】
Git 常用指令速查表 Git 常用指令速查表目录1. 初始化仓库2. 提交代码流程3. 分支管理4. 远程仓库操作5. 撤销操作6. 查看状态与日志7. 其他实用指令完整操作示例常用场景速查表 Git 常用指令速查表 目录 初始化仓库提交代码流程分支管理远程仓库操作撤销操作查看状态与日志其…...
Linux实用操作及命令
一、各类小技巧(快捷键) 1、强制停止(ctrlc) Linux某些程序的运行,如果想要强制停止它,可以使用快捷键ctrl c 命令输入错误,也可以通过快捷键ctrl c,退出当前输入,重…...
洛谷 P10516 数据结构 Solution
Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1,a2,⋯,an) 和 b ( b 1 , b 2 , ⋯ , b n ) b(b_1,b_2,\cdots,b_n) b(b1,b2,⋯,bn),有 m m m 个操作分三种: add ( l , r , k , t ) \operatorname{ad…...
在IDEA中使用TortoiseSVN
一、前言 原版SVN由于下载路径中没有svn.exe文件,导致IDEA中无法使用命令行提交项目代码,因此,现在卸载旧版本TortoiseSVN,下载附有svn.exe的新版TortoiseSVN,下载使用过程记录如下 二、下载过程 卸载就在 控制面板…...
基于 ffmpeg 实现合并视频
ffmpeg是一个强大的多媒体处理工具,支持视频文件的合并。 列出目录下所有MP4文件 import os import glob# 当前目录 directory os.getcwd() directory "/directory/to/mp4/*"# 列出目录下所有MP4文件 files glob.glob(directory)# 排序 files.sort(…...
如何在 HTML 中嵌入外部字体,有哪些注意事项?
大白话如何在 HTML 中嵌入外部字体,有哪些注意事项? 在 HTML 里嵌入外部字体,能让网页文字更有个性,瞬间提升页面的吸引力。下面就来详细说说怎么嵌入外部字体,以及其中的注意事项。 嵌入外部字体的方法 1. 使用 fo…...
三极管原理及应用
一、结构 基极(Base,符号:B) 基极是三极管的控制端,用于输入控制信号。通过基极电流的大小,可以控制集电极与发射极之间的电流导通程度,实现电流放大或开关功能。 发射极(Emitter&…...
三个串口同时打开并指定数据包控制指令思想
可以对嵌入式串口数据包指令设置做一次总结: 首先确定你的数据包大小,传统的接收串口数据到数组存储会出现需要循环遍历数组去读取数据的弊端,所以我设计了一个机制,只有当你想要读取外界指令时,才开始读取外界发过来…...
“征服HTML引号恶魔:“完全解析手册”!!!(quot;表示双引号)
🚨📢 "征服HTML引号恶魔:“完全解析手册” 📢🚨 🎯 博客引言:当引号变成"恶魔" 😱 是否遇到过这种情况: 写HTML时满心欢喜输入<div title"他…...
MQL5教程 04 脚本开发实战、指标开发基础
文章目录 一、脚本开发实战1、给脚本设置快捷键2、运行时显示输入参数界面3、开市价单4、一键平仓5、修改止盈止损6、一键删除当前图表所有挂单 二、指标开发基础 一、脚本开发实战 1、给脚本设置快捷键 在MT5导航栏中,选定脚本,鼠标右击 → 设置热键 …...
【Qt】Ubuntu22.04使用命令安装Qt5和Qt6
1、安装Qt5 注意:Ubuntu22.04已经没有 qt5-default ,因此不能一键安装啦 1)安装核心组件 sudo apt install qtbase5-dev qtchooser qt5-qmake qtcreator2)安装QtCreator sudo apt install qtcreator3)安装工具包、Qt Quick 开发的核心库(qtdeclarative5-dev) sudo a…...
海康设备http监听接收报警事件数据
http监听接收报警事件数据 海康获取设备报警事件数据两种方式: 1、sdk 布防监听报警事件数据(前面文章有示例) 2、http监听接收报警事件数据 http监听接收报警事件数据,服务端可以使用netty通过端口来监听获取事件数据。 WEB 端…...
【MVCC快照如何实现】
MVCC(多版本并发控制)快照的实现原理 MVCC(Multi-Version Concurrency Control)是现代数据库实现事务隔离级别的核心技术,它通过数据多版本和快照机制来实现高效的并发控制。下面我将详细解析MVCC快照的实现机制。 一、MVCC核心组件 1. 版本链结构 MVCC通过以下…...
STM32中不同FLASH的芯片启动文件选择规则
F103ZET6的FLASH大小是512K,所以选择startup_stm32f10x_hd.s F103C8T6的FLASH大小是64K,所以选择startup_stm32f10x_md.s 移植需要注意的事项: 从ZET6到C8T6,需要更改 1)启动文件 2)C/C选项卡...
树莓集团商业模式解析:树莓集团是国企吗?
树莓集团作为中国市场的重要企业实体,其所有制性质一直受到业界关注。从公开资料显示,树莓集团并非传统意义上的国有企业,而是一家具有混合所有制特征的现代化企业集团。其股权结构中既包含国有资本成分,也吸纳了社会资本和民营投…...
mock.js模拟数据
MOCK模拟后端数据 1.按照mock.js npm install mockjs2.在src目录下建立mock目录,在该目录下建立index.js文件,该文件中写上你所需要的数据,示例如下: import Mock from mockjs let data Mock.mock("/data/person",&…...
如何自动规整化(格式化)HTML
如果你想要自动规整化(格式化)HTML,可以使用以下方法: 方法 1:使用 VS Code 进行 HTML 格式化(推荐) 步骤 安装 Visual Studio Code打开你的 HTML 文件按下 Shift Alt F(Windows…...