正点原子STM32(基于HAL库)2

news2025/1/14 1:15:56

目录

  • STM32 基础知识入门
    • 寄存器基础知识
    • STM32F103 系统架构
      • Cortex M3 内核& 芯片
      • STM32 系统架构
      • 存储器映射
      • 寄存器映射
  • 新建寄存器版本MDK 工程

STM32 基础知识入门

寄存器基础知识

寄存器(Register)是单片机内部一种特殊的内存,它可以实现对单片机各个功能的控制,简单的来说可以把寄存器当成一些控制开关,控制包括内核及外设的各种状态。所以无论是51单片机还是STM32,都需要用寄存器来实现各种控制,以完成不同的功能。

由于寄存器资源非常宝贵,一般都是一个位或者几个位控制一个功能,对于STM32 来说,其寄存器是32 位的,一个32 位的寄存器,可能会有32 个控制功能,相当于32 个开关,由于STM32 的复杂性,它内部有几百个寄存器,所以整体来说STM32 的寄存器还是比较复杂的。
不过,我们不要被其吓到了,实际上STM32 是由于内部有很多外设,所以导致寄存器很多,实际上我们把它分好类,每个外设也就那么几个或者几十个寄存器,学起来就不难了。

从大方向来区分,STM32 寄存器分为两类,如表5.2.1 所示:

在这里插入图片描述

其中,内核寄存器,我们一般只需要关心中断控制寄存器和SysTick 寄存器即可,其他三大类,我们一般很少直接接触。而外设寄存器,则是学到哪个外设,就了解哪个外设相关寄存器即可,所以整体来说,我们需要关心的寄存器并不是很多,而且很多都是有共性的,比如STM32F103ZET6 有8 个定时器,我们只需要学习了其中一个的相关寄存器,其他7 个基本都是一样。

说了这么多,给大家举个简单的例子,我们知道寄存器的本质是一个特殊的内存,对于STM32 来说,以GPIOB 的ODR 寄存器为例,其寄存器地址为:0X40010C0C,所以我们对其赋值可以写成:

(*(unsigned int *))(0X40010C0C) = 0XFFFF;

这样我们就完成了对GPIOB->ODR 寄存器的赋值,全部0XFFFF,表示GPIOB 所有IO 口(16 个IO 口)都输出高电平。对于我们来说,0X40010C0C 就是一个寄存器的特殊地址,至于它是怎么来的,我们后续再给大家介绍。

虽然上面的代码实现了我们需要的功能,但是从实用的角度来说,这么写肯定是不好的,可读性极差,可维护性也很差,所以一般我们使用结构体来访问,比如改写成这样:

GPIOB->ODR = 0XFFFF;

这样可读性就比之前的代码好多了,可维护性也相对好一点。至于GPIOB 结构体怎么来的,我们也会在后续给大家介绍。

STM32F103 系统架构

STM32F103 是ST 公司基于ARM 授权Cortex M3 内核而设计的一款芯片,而Cortex M 内核使用的是ARM v7-M 架构,是为了替代老旧的单片机而量身定做的一个内核,具有低成本、低功耗、实时性好、中断响应快、处理效率高等特点。

Cortex M3 内核& 芯片

ARM公司提供内核(如Cortex M3,简称CM3,下同)授权,完整的MCU还需要很多其他组件。芯片公司(ST、NXP、TI、GD、华大等)在得到CM3内核授权后,就可以把CM3内核用在自己的硅片设计中,添加:存储器,外设,I/O以及其它功能块。不同厂家设计出的单片机会有不同的配置,包括存储器容量、类型、外设等都各具特色,因此才会有市面上各种不同应用的ARM芯片。Cortex M3内核和芯片的关系如图5.3.1.1所示:

在这里插入图片描述
可以看到,ARM公司提供CM3内核和调试系统,其他的东西(外设(IIC、SPI、UART、TIM等)、存储器(SRAM、FLASH等)、I/O等)由芯片制造商设计开发。这里ST公司就是STM32F103芯片的制造商。

STM32 系统架构

STM32F103ZET6 内部系统结构如图5.3.2.1:
在这里插入图片描述

STM32F103的系统主要由:四个驱动单元(可以主动发起通信,图中①区域)和四个被动单元(只能被驱动工作,图中②区域)组成,如表5.3.2.1所示:
在这里插入图片描述
这里的驱动/被动单元都是指连接了总线矩阵的部分,未连接总线矩阵的部分,则不算作驱动/被驱动单元。接下来我们介绍一下这些单元。
1. I Code 总线(I - Bus)
这是Cortex M3内核的指令总线,连接闪存指令接口(如:FLASH),用于获取指令。由于该总线功能单一,并没有直接连接到总线矩阵,因此被排除在驱动单元之外。
2. D Code 总线(D - Bus)
这是Cortex M3内核的数据总线,连接闪存存储器数据接口(如:SRAM、FLASH等),用于各种数据访问,如常量、变量等。
3. 系统总线(S - Bus)
这是Cortex M3内核的系统总线,连接所有外设(如:GPIO、SPI、IIC、TIM等),用于控制各种外设工作,如配置各种外设相关寄存器等。

4. DMA 总线
DMA是直接存储访问控制器,可以实现数据的自动搬运,整个过程不需要CPU处理。如可以实现DMA传输内存数据到DAC,输出任意波形,传输过程不需要CPU参与,可以大大节省CPU
支,从而更高效的处理事务。STM32F103ZET6内部有2个DMA控制器,可以实现内存到外设、外设到内存、内存到内存的数据传输。
5. 内部FLASH
内部FLASH即单片机的硬盘,用于代码/数据存储,CPU通过ICode总线经FLASH接口访问内部FLASH,FLASH最高访问速度是24Mhz,因此以72M速度访问时,需要插入2个时钟周期延迟。
6. 内部SRAM
内部SRAM即单片机的内存,用于数据存储,直接挂载在总线矩阵上面,CPU通过DCode总线实现0等待延时访问SRAM,最快总线频率可达72Mhz,从而保证高效高速的访问内存。
7. FSMC
FSMC即灵活的静态存储控制器,实际上就是一个外部总线接口,可以用来访问外部SRAM、NAND/NOR FLASH、LCD等。它也是直接挂在总线矩阵上面的,以方便CPU快速访问外挂器件。
8. AHB/APB 桥
AHB总线连接总线矩阵,同时通过2个APB桥连接APB1和APB2,AHB总线速度最大为72Mhz,APB2总线速度最大也是72Mhz,但是APB1总线速度最大只能是36Mhz。这三个总线上面挂载了STM32内部绝大部分外设。
9. 总线矩阵
总线矩阵协调内核系统总线和DMA主控总线之间的访问仲裁,仲裁利用轮换算法,保证各个总线之间的有序访问,从而确保工作正常。

存储器映射

STM32是一个32位单片机,他可以很方便的访问4GB以内的存储空间(2^32 = 4GB),因此Cortex M3内核将图5.3.2.1中的所有结构,包括:FLASH、SRAM、外设及相关寄存器等全部组织在同一个4GB的线性地址空间内,我们可以通过C语言来访问这些地址空间,从而操作相关外设(读/写)。数据字节以小端格式(小端模式)存放在存储器中,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

存储器本身是没有地址信息的,我们对存储器分配地址的过程就叫存储器映射。这个分配一般由芯片厂商做好了,ST将所有的存储器及外设资源都映射在一个4GB的地址空间上(8个块),从而可以通过访问对应的地址,访问具体的外设。其映射关系如图5.3.3.1所示:

在这里插入图片描述

存储块功能介绍
ST将4GB空间分成8个块,每个块512MB,如上图所示,从图中我们可以看出有很多保留区域(Reserved),这是因为一般的芯片制造厂家是不可能把4GB空间用完的,同时,为了方便后续型号升级,会将一些空间预留(Reserved)。8个存储块的功能如表5.3.3.1所示:
在这里插入图片描述
这里我们重点挑前面3个存储块给大家介绍。第一个块是Block 0,用于存储代码,即FLASH空间,其功能划分如表5.3.3.2所示:
在这里插入图片描述
可以看到,我们用户FLASH大小是512KB,这是对于我们使用的STM32F103ZET6来说,如果是其他型号,可能FLASH会更小,当然,如果ST喜欢,也是可以随时推出更大容量的STM32F103单片机的,因为这里保留了一大块地址空间。还有,STM32的出厂固化BootLoader非常精简,整个BootLoder只占了2KB FLASH空间。

第二个块是Block 1,用于存储数据,即SRAM空间,其功能划分如表5.3.3.3所示:
在这里插入图片描述
这个块仅使用了64KB 大小(仅大容量STM32F103 型号才有这么多SRAM ,比如STM32F103ZET6等),用于SRAM访问,同时也有大量保留地址用于扩展。

第三个块是Block 2,用于外设访问,STM32内部大部分的外设都是放在这个块里面的,该存储块里面包括了AHB、APB1和APB2三个总线相关的外设,其中AHB和APB2是高速总线(72Mhz max),APB1是低速总线(36M max)。其功能划分如表5.3.3.4所示:
在这里插入图片描述

同样可以看到,各个总线之间,都有预留地址空间,方便后续扩展。关于STM32各个外设具体挂在哪个总线上面,大家可以参考前面的STM32F103系统结构图和STM32F103存储器映射图进行查找对应。

寄存器映射

给存储器分配地址的过程叫存储器映射,寄存器是一类特殊的存储器,它的每个位都有特定的功能,可以实现对外设/功能的控制,给寄存器的地址命名的过程就叫寄存器映射。

举个简单的例子,大家家里面的纸张就好比通用存储器,用来记录数据是没问题的,但是不会有具体的动作,只能做记录,而你家里面的电灯开关,就好比寄存器了,假设你家有8个灯,就有8个开关(相当于一个8位寄存器),这些开关也可以记录状态,同时还能让电灯点亮/关闭,是会产生具体动作的。为了方便区分和使用,我们会给每个开关命名,比如厨房开关、大厅开关、卧室开关等,给开关命名的过程,就是寄存器映射。

当然STM32内部的寄存器有非常多,远远不止8个开关这么简单,但是原理是差不多的,每个寄存器的每一个位,一般都有特定的作用,涉及到寄存器描述,大家可以参考《STM32F10XXX
参考手册(中文版)_V10.pdf》相关章节的寄存器描述部分,有详细的描述。
1. 寄存器描述解读
我们以GPIO的ODR寄存器为例,其参考手册的描述如图5.3.4.1所示:
在这里插入图片描述
①寄存器名字
每个寄存器都有一个对应的名字,以简单表达其作用,并方便记忆,这里GPIOx_ODR表示寄存器英文名,x可以从A~E,说明有5个这样的寄存器(每个端口有一个,事实上最新的STM32F103型号,可能还有F,G等端口,IO数量更多)。
②寄存器偏移量及复位值
地址偏移量表示相对该外设基地址的偏移,比如GPIOB,我们由图5.3.3.1可知其外设基地址是:0x4001 0C00。那么GPIOB_ODR寄存器的地址就是:0x4001 0C0C。知道了外设基地址和地址偏移量,我们就可以知道任何一个寄存器的实际地址。
复位值表示该寄存器在系统复位后的默认值,可以用于分析外设的默认状态。这里全部是0。
③寄存器位表
描述寄存器每一个位的作用(共32bit),这里表示ODR寄存器的第15位(bit),位名字为ODR15,rw表示该寄存器可读写(r,可读取;w,可写入)。
④位功能描述

描述寄存器每个位的功能,这里表示位015,对应ODR0ODR15,每个位控制一个IO口的输出状态。
其他寄存器描述,参照以上方法解读接口。

2. 寄存器映射举例
从前面的学习我们知道GPIOB_ODR 寄存器的地址为:0x4001 0C0C,假设我们要控制GPIOB的16个IO口都输出1,则可以写成:

*(unsigned int *)(0x40010C0C) = 0XFFFF;

这里我们先要将0x4001 0C0C 强制转换成unsigned int 类型指针,然后用*对这个指针的值进行设置,从而完成对GPIOB_ODR 寄存器的写入。
这样写代码功能是没问题,但是可读性和可维护性都很差,使用起来极其不便,因此我们将代码改为:

#define GPIOB_ODR *(unsigned int *)(0x40010C0C)
GPIOB_ODR = 0XFFFF;

这样,我们就定义了一个GPIOB_ODR 的宏,来替代数值操作,很明显,GPIOB_ODR 的可读性和可维护性,比直接使用数值操作来的直观和方便。这个宏定义过程就可以称之为寄存器的映射。

当然,为了简单,我们只举了一个简单实例,实际上大量寄存器的映射,使用结构体是最方便的方式,stm32f103xe.h 里面使用结构体方式对STM32F103 的寄存器做了详细映射,等下我们再介绍。
3. 寄存器地址计算
STM32F103大部分外设寄存器地址都是在存储块2上面的,见图5.3.3.1。具体某个寄存器地址,由三个参数决定:1、总线基地址(BUS_BASE_ADDR);2,外设基于总线基地址的偏移量(PERIPH_OFFSET);3,寄存器相对外设基地址的偏移量(REG_OFFSET)。可以表示为:

寄存器地址= BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
总线基地址(BUS_BASE_ADDR),STM32F103内部有三个总线(APB1、APB2和AHB),对应的总线基地址如表5.3.4.1所示:
在这里插入图片描述
上表中APB1的基地址,也叫外设基地址,表中的偏移量就是相对于外设基地址的偏移量。

注意:AHB的总线基地址是0X4001 8000,从该基地址到0X4002 0000,只挂了SDIO一个外设,后续的AHB外设基地址都大于等于0X4002 0000。为了方便计算,我们可以将AHB的总线基地址改成:0X4002 0000,而SDIO则单独定义一个基地址给他即可。

外设基于总线基地址的偏移量(PERIPH_OFFSET),这个不同外设偏移量不一样,我们可以在STM32F103存储器映射图(图5.3.3.1)里面找到具体的偏移量,以GPIO为例,其偏移量如表5.3.4.2所示:
在这里插入图片描述
上表的偏移量,就是外设基于APB2总线基地址的偏移量(PERIPH_OFFSET)。

知道了外设基地址,再在参考手册里面找到具体某个寄存器相对外设基地址的偏移量就可以知道该寄存器的实际地址了,以GPIOB的相关寄存器为例,如表5.3.4.3所示:
在这里插入图片描述
上表的偏移量,就是寄存器基于外设基地址的偏移量(REG_OFFSET)。

因此,我们根据前面的公式,很容易可以计算出GPIOB_ODR的地址:

GPIOB_ODR地址= APB2总线基地址+ GPIOB外设偏移量+ 寄存器偏移量

所以得到:GPIOB_ODR 地址= 0X4001 0000 + 0XC00 + 0X0C = 0X4001 0C0C关于寄存器地址计算我们就讲到这里,通过本节的学习,其他寄存器的地址大家都应该可以熟练掌握并计算出来。

4. stm32f103xe.h 寄存器映射说明

STM32F103所有寄存器映射都在stm32f103xe.h里面完成,包括各种基地址定义、结构体定义、外设寄存器映射、寄存器位定义(占了绝大部分)等,整个文件有1W多行,非常庞大。我们没有必要对该文件进行全面分析,因为很多内容都是相似的,我们只需要知道寄存器是如何被映射的,就可以了,至于寄存器位定义这些内容,知道是怎么回事就可以了。

我们还是以GPIO为例进行说明,看看stm32f103xe.h是如何对GPIO的寄存器进行映射的,通过对GPIO寄存器映射,了解stm32f103xe.h的映射规则。

stm32f103xe.h文件主要包含五个部分内容,如表5.3.4.4所示:
在这里插入图片描述
寄存器映射主要涉及到表5.3.4.4中加粗的两个组成部分:外设寄存器结构体类型定义和寄存器映射,总结起来,包括3个步骤:
1,外设寄存器结构体类型定义
2,外设基地址定义
3,寄存器映射(通过将外设基地址强制转换为外设结构体类型指针即可)
以GPIO为例,其寄存器结构体类型定义如下:

typedef struct
{
	__IO uint32_t CRL; /* GPIO_CRL 寄存器,相对外设基地址偏移量:0X00 */
	__IO uint32_t CRH; /* GPIO_CRH 寄存器,相对外设基地址偏移量:0X04 */
	__IO uint32_t IDR; /* GPIO_IDR 寄存器,相对外设基地址偏移量:0X08 */
	__IO uint32_t ODR; /* GPIO_ODR 寄存器,相对外设基地址偏移量:0X0C */
	__IO uint32_t BSRR; /* GPIO_BSRR寄存器,相对外设基地址偏移量:0X10 */
	__IO uint32_t BRR; /* GPIO_BRR 寄存器,相对外设基地址偏移量:0X14 */
	__IO uint32_t LCKR; /* GPIO_LCKR寄存器,相对外设基地址偏移量:0X18 */
} GPIO_TypeDef;

GPIO外设基地址定义如下:

#define PERIPH_BASE 0x40000000UL /* 外设基地址*/
#define APB1PERIPH_BASE PERIPH_BASE /* APB1总线基地址*/
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) /* APB2总线基地址*/
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000UL) /* AHB总线基地址*/
#define GPIOA_BASE (APB2PERIPH_BASE + 0x00000800UL) /* GPIOA基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x00000C00UL) /* GPIOB基地址*/
#define GPIOC_BASE (APB2PERIPH_BASE + 0x00001000UL) /* GPIOC基地址*/
#define GPIOD_BASE (APB2PERIPH_BASE + 0x00001400UL) /* GPIOD基地址*/
#define GPIOE_BASE (APB2PERIPH_BASE + 0x00001800UL) /* GPIOE基地址*/
#define GPIOF_BASE (APB2PERIPH_BASE + 0x00001C00UL) /* GPIOF基地址*/
#define GPIOG_BASE (APB2PERIPH_BASE + 0x00002000UL) /* GPIOG基地址*/

GPIO外设寄存器映射定义如下:

#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE) /* GPIOA寄存器地址映射*/
#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) /* GPIOB寄存器地址映射*/
#define GPIOC ((GPIO_TypeDef *)GPIOC_BASE) /* GPIOC寄存器地址映射*/
#define GPIOD ((GPIO_TypeDef *)GPIOD_BASE) /* GPIOD寄存器地址映射*/
#define GPIOE ((GPIO_TypeDef *)GPIOE_BASE) /* GPIOE寄存器地址映射*/
#define GPIOF ((GPIO_TypeDef *)GPIOF_BASE) /* GPIOF寄存器地址映射*/
#define GPIOG ((GPIO_TypeDef *)GPIOG_BASE) /* GPIOG寄存器地址映射*/

以上三部分代码,就完成了STM32F103内部GPIOA~GPIOG的寄存器映射,其原理其实是比较简单的,包括两个核心知识点:1,结构体地址自增;2,地址强制转换;

结构体地址自增,我们第一步就定义了GPIO_TypeDef结构体类型,其成员包括:CRL、CRH、IDR、ODR、BSRR、BRR和LCKR,每个成员是uint32_t类型,也就是4个字节,这样假设:CRL地址是0的话,CRH就是0X04,IDR就是0X08,ODR就是0X0C,以此类推。

地址强制转换,以GPIOB为例,GPIOB外设的基地址为:GPIOB_BASE(0X4001 0C00),我们使用GPIO_TypeDef将该地址强制转换为GPIO结构体类型指针:GPIOB,这样GPIOB->CRL
的地址就是:GPIOB_BASE(0X4001 0C00),GPIOB->CRH的地址就是:GPIOB_BASE + 0X04(0X4001 0C04),GPIOB->IDR的地址就是:GPIOB_BASE + 0X08(0X4001 0C08),以此类推。

这样我们就使用结构体方式完成了对GPIO寄存器的映射,其他外设的寄存器映射也都是这个方法,这里就不一一介绍了。关于stm32f103xe.h的寄存器映射,我们就介绍到这里。

新建寄存器版本MDK 工程

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

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

相关文章

【自学Docker】Docker HelloWorld

Docker HelloWorld Docker服务 查看Docker服务状态 使用 systemctl status docker 命令查看 Docker 服务的状态。 haicoder(www.haicoder.net)# systemctl status docker我们使用 systemctl status docker 命令查看 Docker 服务的状态,显示结果如下图所示&#…

HotPDF Delphi PDF编译器形成PDF文档

HotPDF Delphi PDF编译器形成PDF文档 HotPDF Delphi PDF编译器支持通过内部和外部链接完全形成PDF文档。计算机还完全支持Unicode。此外,在您的产品和软件中使用此计算机的最新功能,您可以指定加密、打印和编辑PDF文档的能力。当您加密PDF文档时&#xf…

Markdown总结

为什么要使用Markdowm 什么是Markdown?为什么需要使用Markdown? Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档。 Markdown 语言在 2004 由约翰格鲁伯(英语:John Gruber)创建。 Markdo…

openEuler 社区 2022 年 12 月运作报告

社区活跃度在社区所有开发者和用户的共同参与下,openEuler的3年持续迸发活力!从0到超过1.27万名开发者,从0到超过100万的社区用户,从0到超过750家企业伙伴加入社区……截至目前,在大家的持续贡献下,openEul…

GemBox.Bundle 47.0.1012 VS Spire.Office Platinum 8.1.1

GemBox.Bundle 是一个 .NET 组件包,使您能够简单高效地处理办公文件(电子表格、文档、演示文稿和电子邮件)。 使用我们的组件,您可以以易于使用的形式快速获得可靠的结果。只需要 .NET,因此您可以轻松部署您的应用程序…

收官!OceanBase第五届技术征文大赛获奖名单公布!

OceanBase 一直在思考,什么样的数据库对用户而言更易用? 更易用,除了功能完善、性能优秀、运行稳定的数据库系统,丰富多样的生态工具也必不可少。 作为一款完全自主研发的原生分布式数据库,OceanBase 的生态工具经历…

基于Java SSM springboot+VUE+redis实现的前后端分类版网上商城项目

基于Java SSM springbootVUEredis实现的前后端分类版网上商城项目 博主介绍:5年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言…

路由 OSPF LSA介绍、1~7类LSA详细介绍

1.0.0 路由 OSPF LSA介绍、1~7类LSA详细介绍 OSPF LSA 链路状态通告( Link status announcement),作用于 向其它邻接OSPF路由器 传递拓扑信息与路由信息。 LSA如何去描述拓扑信息与路由信息的呢? 其实是基于不同类型LSA进行描述,而常见的LS…

EquiBind模型源码分析

EquiBind模型源码分析 使用提供的模型权重来预测你自己的蛋白质配体对的结合结构 第 1 步:你需要什么作为输入 mol2或.sdf或.pdbqt或.pdb格式的配体文件,其名称包含字符串配体(配体文件应包含所有氢)。 .pdb格式的受体文件,其名称包含字符串protein。我…

leetcode.1819 序列中不同最大公约数的数目 - gcd + 枚举

1819. 序列中不同最大公约数的数目 目录 1、java版 2、c版 思路: 有n个元素的数组,则其子序列有 个,而1 ≤ n ≤ ,则不可能枚举每一个子序列计算它的gcd,那样会tle我们可以逆转思路,因为1 ≤ nums[i]…

PhysioNet2017数据集介绍

一、数据集下载 PhysioNet2017为短单导联心电图记录的房颤分类数据集,下载地址如下:https://www.physionet.org/content/challenge-2017/1.0.0/ 二、数据集介绍 PhysioNet2017数据集主要用于对记录是否显示正常窦性心律、心房颤动(AF&…

背包问题= =

一、01背包有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。(下图是例子,一下…

14、ThingsBoard-自定义华为云SMS规则节点

1、概述 一个物联网平台承载着很多设备的连接,当设备出现异常的时候,能够快速的通知到运维管理员是非常重要的,thingsboard提供了自定义配置邮箱,但是它对支持发送短信的不是很友好,都是国外的sms服务商,我反正是不用那个,在国内常见就是阿里、腾讯、华为、七牛常用的s…

【Python百日进阶-数据分析】Day224 - plotly漏斗图px.funnel()

文章目录一、语法二、参数三、返回值四、实例4.1 使用 plotly.express 的漏斗图4.1.1 基本漏斗图4.1.2 堆积漏斗图4.1.3 基本区域漏斗图4.2 使用 plotly.graph_objects 的漏斗图4.2.1 基本漏斗图4.2.2 设置标记大小和颜色4.2.3 堆积漏斗图4.2.4 基本区域漏斗图4.2.5 在区域漏斗…

Postgresql遇到的问题

解决问题之前最好先下载个pgadmin可视化工具,下面可能要用到。先看图,了解基本的\n 代表是当前数据库下面schemas的文件\du 代表你有这写用户(角色),后面代表的权限\l 代表的是你的数据库在敲命令之前你德先进去docker…

excel表格技巧:Ctrl+T在超级表中的妙用

在介绍超级表的其它奇妙功能之前,小编先给大家说一个在创建超级表时应该注意的小细节。在创建超级表的对话框里,有一个“表包含标题”的选项,大家一定要记得勾选哦,不然超级表就会变成下面这样:超级表会自作聪明的在表…

【ROS】package.xml文件解析

文章目录 文章目录 前言 一、基本格式 1.基本结构 2.必要标签 3.依赖关系 二、Metapackage包 总结 前言 ros每个功能包中都有一个包清单,它是一个名为package.xml的XML 文件,它必须包含在任何符合 catkin 的包的根文件夹中。此文件定义有关包的属…

Vue过滤器

Vue过滤器1. 概述2. 全局过滤器与局部过滤器2.1 过滤器参数2.2 过滤器的串联1. 概述 在Vue.js中,过滤器主要用于文本的格式化,或者组件数据的过滤与排序等。从Vue2.0.0版本开始,内置的过滤器已经被删除,需要自己编写。 2. 全局过…

【OpenGL学习】绘制三角形

绘制三角形 上节中完成了窗口的绘制,这节我们主要实现在窗口中完成一个最简单的三角形的绘制,同样,要完成一个三角形的绘制,需要以下内容: Vertex Array 存放顶点数据的数组(实际上存放的是顶点数据的指针…

Imagination与Synopsys携手加快移动端与数据中心3D可视化技术的发展

IMG CXT GPU与Synopsys Fusion QIK一同优化移动光追应用的PPA中国北京 - 2023年1月13日- Imagination Technologies与领先的电子设计自动化(EDA)解决方案和服务商Synopsys一起为移动光追解决方案打造一个更加快速、高效的设计流程。光追技术通过模仿光线…