STM32上电启动过程分析

嵌入式电子 2023-09-24 13:15

一、概述

1、说明

每一款芯片的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道。通过了解启动文件,我们可以体会到处理器的架构、指令集、中断向量安排等内容,是非常值得玩味的。

STM32作为一款高端 Cortex-M3系列单片机,有必要了解它的启动文件。打好基础,为以后优化程序,写出高质量的代码最准备。

本文以一个实际测试代码--START_TEST为例进行阐述。

2、整体过程概括

STM32整个启动过程是指从上电开始,一直到运行到 main函数之间的这段过程,步骤为(以使用微库为例):

①上电后硬件设置SP、PC

②设置系统时钟

③软件设置SP

④加载.data、.bss,并初始化栈区

⑤跳转到C文件的main函数

3、整个启动过程涉及的代码

推荐阅读👉深入理解MCU启动原理

启动过程涉及的文件不仅包含 startup_stm32f10x_hd.s,还涉及到了MDK自带的连接库文件 entry.o、entry2.o、entry5.o、entry7.o等(从生成的 map文件可以看出来)。

二、程序在Flash上的存储结构

在真正讲解启动过程之前,先要讲解程序下载到 Flash上的结构和程序运行时(执行到main函数)时的SRAM数据结构。程序在用户Flash上的结构如下图所示。下图是通过阅读hex文件和在MDK下调试综合提炼出来的。

  1. MSP初始值        编译器生成,主堆栈的初始值


  2. 异常向量表        不多说


  3. 外部中断向量表      不多说


  4. 代码段          存放代码


  5. 初始化数据段       .data


  6. 未初始化数据段      .bss

加载数据段和初始化栈的参数

加载数据段和初始化栈的参数分别有4个,这里只讲解加载数据段的参数,至于初始化栈的参数类似。

  1. 0x0800033c  Flash上的数据段(初始化数据段和未初始化数据段)起始地址


  2. 0x20000000  加载到SRAM上的目的地址


  3. 0x0000000c  数据段的总大小


  4. 0x080002f4  调用函数_scatterload_copy

需要说明的是初始化栈的函数-- 0x08000304与加载数据段的函数不一样,为 _scatterload_zeroinit,它的目的就是将栈空间清零。

三、数据在SRAM上的结构

程序运行时(执行到main函数)时的SRAM数据结构

四、详细过程分析

有了以上的基础,现在详细分析启动过程。

1、上电后硬件设置SP、PC

刚上电复位后,硬件会自动根据向量表偏移地址找到向量表,向量表偏移地址的定义如下:

调试现象如下:

看看我们的向量表内容(通过J-Flash打开hex文件)

硬件这时自动从0x0800 0000位置处读取数据赋给栈指针SP,然后自动从0x0800 0004位置处读取数据赋给PC,完成复位,结果为:

  1. SP = 0x02000810

  2. PC = 0x08000145

2、设置系统时钟

上一步中令 PC=0x08000145的地址没有对齐,硬件自动对齐到 0x08000144,执行 SystemInit函数初始化系统时钟。

3、软件设置SP

  1.   LDR R0,=__main

  2.   BX   R0

执行上两条之类,跳转到 __main程序段运行,注意不是main函数, ___main的地址是0x0800 0130。

可以看到指令LDR.W sp,[pc,#12],结果SP=0x2000 0810。

4、加载.data、.bss,并初始化栈区

  1. BL.W __scatterload_rt2

进入 __scatterload_rt2代码段。

  1. __scatterload_rt2:

  2. 0x080001684C06 LDR r4,[pc,#24] ; @0x08000184

  3. 0x0800016A4D07 LDR r5,[pc,#28] ; @0x08000188

  4. 0x0800016C E006 B 0x0800017C

  5. 0x0800016E68E0 LDR r0,[r4,#0x0C]

  6. 0x08000170 F0400301 ORR r3,r0,#0x01

  7. 0x08000174 E8940007 LDM r4,{r0-r2}

  8. 0x080001784798 BLX r3

  9. 0x0800017A3410 ADDS r4,r4,#0x10

  10. 0x0800017C42AC CMP r4,r5

  11. 0x0800017E D3F6 BCC 0x0800016E

  12. 0x08000180 F7FFFFDA BL.W _main_init (0x08000138)

这段代码是个循环 (BCC0x0800016e),实际运行时候循环了两次。第一次运行的时候,读取“加载数据段的函数 (_scatterload_copy)”的地址并跳转到该函数处运行(注意加载已初始化数据段和未初始化数据段用的是同一个函数);第二次运行的时候,读取“初始化栈的函数 (_scatterload_zeroinit)”的地址并跳转到该函数处运行。相应的代码如下:

  1. 0x0800016E68E0 LDR r0,[r4,#0x0C]

  2. 0x08000170 F0400301 ORR r3,r0,#0x01

  3. 0x08000174

  4. 0x080001784798 BLX r3

当然执行这两个函数的时候,还需要传入参数。至于参数,我们在“加载数据段和初始化栈的参数”环节已经阐述过了。当这两个函数都执行完后,结果就是“数据在SRAM上的结构”所展示的图。最后,也把事实加载和初始化的两个函数代码奉上如下:

  1. __scatterload_copy:

  2. 0x080002F4 E002 B 0x080002FC

  3. 0x080002F6 C808 LDM r0!,{r3}

  4. 0x080002F81F12 SUBS r2,r2,#4

  5. 0x080002FA C108 STM r1!,{r3}

  6. 0x080002FC2A00 CMP r2,#0x00

  7. 0x080002FE D1FA BNE 0x080002F6

  8. 0x080003004770 BX lr

  9. __scatterload_null:

  10. 0x080003024770 BX lr

  11. __scatterload_zeroinit:

  12. 0x080003042000 MOVS r0,#0x00

  13. 0x08000306 E001 B 0x0800030C

  14. 0x08000308 C101 STM r1!,{r0}

  15. 0x0800030A1F12 SUBS r2,r2,#4

  16. 0x0800030C2A00 CMP r2,#0x00

  17. 0x0800030E D1FB BNE 0x08000308

  18. 0x080003104770 BX lr

5、跳转到C文件的main函数

  1. _main_init:

  2. 0x080001384800 LDR r0,[pc,#0] ; @0x0800013C

  3. 0x0800013A4700 BX r0

五、异常向量与中断向量表

  1. ; VectorTableMapped to Address0 at Reset

  2. AREA RESET, DATA, READONLY

  3. EXPORT __Vectors

  4. EXPORT __Vectors_End

  5. EXPORT __Vectors_Size


  6. __Vectors DCD __initial_sp ; Top of Stack

  7. DCD Reset_Handler; ResetHandler

  8. DCD NMI_Handler ; NMI Handler

  9. DCD HardFault_Handler; HardFaultHandler

  10. DCD MemManage_Handler; MPU FaultHandler

  11. DCD BusFault_Handler; BusFaultHandler

  12. DCD UsageFault_Handler; UsageFaultHandler

  13. DCD 0; Reserved

  14. DCD 0; Reserved

  15. DCD 0; Reserved

  16. DCD 0; Reserved

  17. DCD SVC_Handler ; SVCallHandler

  18. DCD DebugMon_Handler; DebugMonitorHandler

  19. DCD 0; Reserved

  20. DCD PendSV_Handler; PendSVHandler

  21. DCD SysTick_Handler; SysTickHandler


  22. ; ExternalInterrupts

  23. DCD WWDG_IRQHandler ; WindowWatchdog

  24. DCD PVD_IRQHandler ; PVD through EXTI Line detect

  25. DCD TAMPER_IRQHandler ; Tamper

  26. DCD RTC_IRQHandler ; RTC

  27. DCD FLASH_IRQHandler ; Flash

  28. DCD RCC_IRQHandler ; RCC

  29. DCD EXTI0_IRQHandler ; EXTI Line0

  30. DCD EXTI1_IRQHandler ; EXTI Line1

  31. DCD EXTI2_IRQHandler ; EXTI Line2

  32. DCD EXTI3_IRQHandler ; EXTI Line3

  33. DCD EXTI4_IRQHandler ; EXTI Line4

  34. DCD DMA1_Channel1_IRQHandler ; DMA1 Channel1

  35. DCD DMA1_Channel2_IRQHandler ; DMA1 Channel2

  36. DCD DMA1_Channel3_IRQHandler ; DMA1 Channel3

  37. DCD DMA1_Channel4_IRQHandler ; DMA1 Channel4

  38. DCD DMA1_Channel5_IRQHandler ; DMA1 Channel5

  39. DCD DMA1_Channel6_IRQHandler ; DMA1 Channel6

  40. DCD DMA1_Channel7_IRQHandler ; DMA1 Channel7

  41. DCD ADC1_2_IRQHandler ; ADC1 & ADC2

  42. DCD USB_HP_CAN1_TX_IRQHandler ; USB HighPriority or CAN1 TX

  43. DCD USB_LP_CAN1_RX0_IRQHandler ; USB LowPriority or CAN1 RX0

  44. DCD CAN1_RX1_IRQHandler ; CAN1 RX1

  45. DCD CAN1_SCE_IRQHandler ; CAN1 SCE

  46. DCD EXTI9_5_IRQHandler ; EXTI Line9..5

  47. DCD TIM1_BRK_IRQHandler ; TIM1 Break

  48. DCD TIM1_UP_IRQHandler ; TIM1 Update

  49. DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation

  50. DCD TIM1_CC_IRQHandler ; TIM1 CaptureCompare

  51. DCD TIM2_IRQHandler ; TIM2

  52. DCD TIM3_IRQHandler ; TIM3

  53. DCD TIM4_IRQHandler ; TIM4

  54. DCD I2C1_EV_IRQHandler ; I2C1 Event

  55. DCD I2C1_ER_IRQHandler ; I2C1 Error

  56. DCD I2C2_EV_IRQHandler ; I2C2 Event

  57. DCD I2C2_ER_IRQHandler ; I2C2 Error

  58. DCD SPI1_IRQHandler ; SPI1

  59. DCD SPI2_IRQHandler ; SPI2

  60. DCD USART1_IRQHandler ; USART1

  61. DCD USART2_IRQHandler ; USART2

  62. DCD USART3_IRQHandler ; USART3

  63. DCD EXTI15_10_IRQHandler ; EXTI Line15..10

  64. DCD RTCAlarm_IRQHandler; RTC Alarm through EXTI Line

  65. DCD USBWakeUp_IRQHandler; USB Wakeup from suspend

  66. DCD TIM8_BRK_IRQHandler ; TIM8 Break

  67. DCD TIM8_UP_IRQHandler ; TIM8 Update

  68. DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation

  69. DCD TIM8_CC_IRQHandler ; TIM8 CaptureCompare

  70. DCD ADC3_IRQHandler ; ADC3

  71. DCD FSMC_IRQHandler ; FSMC

  72. DCD SDIO_IRQHandler ; SDIO

  73. DCD TIM5_IRQHandler ; TIM5

  74. DCD SPI3_IRQHandler ; SPI3

  75. DCD UART4_IRQHandler ; UART4

  76. DCD UART5_IRQHandler ; UART5

  77. DCD TIM6_IRQHandler ; TIM6

  78. DCD TIM7_IRQHandler ; TIM7

  79. DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1

  80. DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2

  81. DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3

  82. DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4& Channel5

  83. __Vectors_End

这段代码就是定义异常向量表,在之前有一个“J-Flash打开hex文件”的图片跟这个表格是一一对应的。编译器根据我们定义的函数 Reset_Handler、NMI_Handler等,在连接程序阶段将这个向量表填入这些函数的地址。

  1. startup_stm32f10x_hd.s内容:


  2. N MI_Handler PROC

  3. EXPORT NMI_Handler [WEAK]

  4. B .

  5. ENDP



  6. stm32f10x_it.c中内容:

  7. void NMI_Handler(void)

  8. {

  9. }

在启动汇编文件中已经定义了函数 NMI_Handler,但是使用了“弱”,它允许我们再重新定义一个 NMI_Handler函数,程序在编译的时候会将汇编文件中的弱函数“覆盖掉”--两个函数的代码在连接后都存在,只是在中断向量表中的地址填入的是我们重新定义函数的地址。

六、使用微库与不使用微库的区别

使用微库就意味着我们不想使用MDK提供的库函数,而想用自己定义的库函数,比如说printf函数。那么这一点是怎样实现的呢?我们以printf函数为例进行说明。

1、不使用微库而使用系统库

在连接程序时,肯定会把系统中包含printf函数的库拿来调用参与连接,即代码段有系统库的参与。

在启动过程中,不使用微库而使用系统库在初始化栈的时候,还需要初始化堆(猜测系统库需要用到堆),而使用微库则是不需要的。

  1. IF :DEF:__MICROLIB


  2. EXPORT __initial_sp

  3. EXPORT __heap_base

  4. EXPORT __heap_limit


  5. ELSE


  6. IMPORT __use_two_region_memory

  7. EXPORT __user_initial_stackheap


  8. __user_initial_stackheap


  9. LDR R0, = Heap_Mem

  10. LDR R1, =(Stack_Mem+ Stack_Size)

  11. LDR R2, = (Heap_Mem+ Heap_Size)

  12. LDR R3, = Stack_Mem

  13. BX LR


  14. ALIGN


  15. ENDIF

另外,在执行 __main函数的过程中,不仅需要完成“使用微库”情况下的所有工作,额外的工作还需要进行库的初始化,才能使用系统库(这一部分我还没有深入探讨)。附上 __main函数的内容:

  1. __main:

  2. 0x08000130 F000F802 BL.W __scatterload_rt2_thumb_only (0x08000138)

  3. 0x08000134 F000F83C BL.W __rt_entry_sh (0x080001B0)

  4. __scatterload_rt2_thumb_only:

  5. 0x08000138 A00A ADR r0,{pc}+4; @0x08000164

  6. 0x0800013A E8900C00 LDM r0,{r10-r11}

  7. 0x0800013E4482 ADD r10,r10,r0

  8. 0x080001404483 ADD r11,r11,r0

  9. 0x08000142 F1AA0701 SUB r7,r10,#0x01

  10. __scatterload_null:

  11. 0x0800014645DA CMP r10,r11

  12. 0x08000148 D101 BNE 0x0800014E

  13. 0x0800014A F000F831 BL.W __rt_entry_sh (0x080001B0)

  14. 0x0800014E F2AF0E09 ADR.W lr,{pc}-0x07; @0x08000147

  15. 0x08000152 E8BA000F LDM r10!,{r0-r3}

  16. 0x08000156 F0130F01 TST r3,#0x01

  17. 0x0800015A BF18 IT NE

  18. 0x0800015C1AFB SUBNE r3,r7,r3

  19. 0x0800015E F0430301 ORR r3,r3,#0x01

  20. 0x080001624718 BX r3

  21. 0x080001640298 LSLS r0,r3,#10

  22. 0x080001660000 MOVS r0,r0

  23. 0x0800016802B8 LSLS r0,r7,#10

  24. 0x0800016A0000 MOVS r0,r0

  25. __scatterload_copy:

  26. 0x0800016C3A10 SUBS r2,r2,#0x10

  27. 0x0800016E BF24 ITT CS

  28. 0x08000170 C878 LDMCS r0!,{r3-r6}

  29. 0x08000172 C178 STMCS r1!,{r3-r6}

  30. 0x08000174 D8FA BHI __scatterload_copy (0x0800016C)

  31. 0x080001760752 LSLS r2,r2,#29

  32. 0x08000178 BF24 ITT CS

  33. 0x0800017A C830 LDMCS r0!,{r4-r5}

  34. 0x0800017C C130 STMCS r1!,{r4-r5}

  35. 0x0800017E BF44 ITT MI

  36. 0x080001806804 LDRMI r4,[r0,#0x00]

  37. 0x08000182600C STRMI r4,[r1,#0x00]

  38. 0x080001844770 BX lr

  39. 0x080001860000 MOVS r0,r0

  40. __scatterload_zeroinit:

  41. 0x080001882300 MOVS r3,#0x00

  42. 0x0800018A2400 MOVS r4,#0x00

  43. 0x0800018C2500 MOVS r5,#0x00

  44. 0x0800018E2600 MOVS r6,#0x00

  45. 0x080001903A10 SUBS r2,r2,#0x10

  46. 0x08000192 BF28 IT CS

  47. 0x08000194 C178 STMCS r1!,{r3-r6}

  48. 0x08000196 D8FB BHI 0x08000190

  49. 0x080001980752 LSLS r2,r2,#29

  50. 0x0800019A BF28 IT CS

  51. 0x0800019C C130 STMCS r1!,{r4-r5}

  52. 0x0800019E BF48 IT MI

  53. 0x080001A0600B STRMI r3,[r1,#0x00]

  54. 0x080001A24770 BX lr

  55. __rt_lib_init:

  56. 0x080001A4 B51F PUSH {r0-r4,lr}

  57. 0x080001A6 F3AF8000 NOP.W

  58. __rt_lib_init_user_alloc_1:

  59. 0x080001AA BD1F POP {r0-r4,pc}

  60. __rt_lib_shutdown:

  61. 0x080001AC B510 PUSH {r4,lr}

  62. __rt_lib_shutdown_user_alloc_1:

  63. 0x080001AE BD10 POP {r4,pc}

  64. __rt_entry_sh:

  65. 0x080001B0 F000F82F BL.W __user_setup_stackheap (0x08000212)

  66. 0x080001B44611 MOV r1,r2

  67. __rt_entry_postsh_1:

  68. 0x080001B6 F7FFFFF5 BL.W __rt_lib_init (0x080001A4)

  69. __rt_entry_postli_1:

  70. 0x080001BA F000F919 BL.W main (0x080003F0)

2、使用微库而不使用系统库

在程序连接时,不会把包含printf函数的库连接到终极目标文件中,而使用我们定义的库。

启动时需要完成的工作就是之前论述的步骤1、2、3、4、5,相比使用系统库,启动过程步骤更少。


定期以通俗易懂的方式分享嵌入式知识,关注公众号,加星标,每天进步一点点。


声明:

本号原创、转载的文章、图片等版权归原作者所有,如有侵权,请联系删除。

关注、点赞、在看、转发,支持优质内容! 

评论 (0)
  • 随着智能驾驶时代到来,汽车正转变为移动计算平台。车载AI技术对存储器提出新挑战:既要高性能,又需低功耗和车规级可靠性。贞光科技代理的紫光国芯车规级LPDDR4存储器,以其卓越性能成为国产芯片产业链中的关键一环,为智能汽车提供坚实的"记忆力"支持。作为官方授权代理商,贞光科技通过专业技术团队和完善供应链,让这款国产存储器更好地服务国内汽车厂商。本文将探讨车载AI算力需求现状及贞光科技如何通过紫光国芯LPDDR4产品满足市场需求。 车载AI算力需求激增的背景与挑战智能驾驶推动算力需求爆发式
    贞光科技 2025-05-07 16:54 202浏览
  • 后摄像头是长这个样子,如下图。5孔(D-,D+,5V,12V,GND),说的是连接线的个数,如下图。4LED,+12V驱动4颗LED灯珠,给摄像头补光用的,如下图。打开后盖,发现里面有透明白胶(防水)和白色硬胶(固定),用合适的工具,清理其中的胶状物。BOT层,AN3860,Panasonic Semiconductor (松下电器)制造的,Cylinder Motor Driver IC for Video Camera,如下图。TOP层,感光芯片和广角聚焦镜头组合,如下图。感光芯片,看着是玻
    liweicheng 2025-05-07 23:55 402浏览
  • 二位半 5线数码管的驱动方法这个2位半的7段数码管只用5个管脚驱动。如果用常规的7段+共阳/阴则需要用10个管脚。如果把每个段看成独立的灯。5个管脚来点亮,任选其中一个作为COM端时,另外4条线可以单独各控制一个灯。所以实际上最多能驱动5*4 = 20个段。但是这里会有一个小问题。如果想点亮B1,可以让第3条线(P3)置高,P4 置低,其它阳极连P3的灯对应阴极P2 P1都应置高,此时会发现C1也会点亮。实际操作时,可以把COM端线P3设置为PP输出,其它线为OD输出。就可以单独控制了。实际的驱
    southcreek 2025-05-07 15:06 497浏览
  • 文/Leon编辑/cc孙聪颖‍《中国家族企业传承研究报告》显示,超四成“企二代” 明确表达接班意愿,展现出对家族企业延续发展的主动担当。中国研究数据服务平台(CNRDS)提供的精准数据进一步佐证:截至 2022 年,已有至少 280 家上市家族企业完成权杖交接,其中八成新任掌门人为创始人之子,凸显家族企业代际传承中 “子承父业” 的主流模式。然而,对于“企二代” 而言,接棒掌舵绝非易事。在瞬息万变的商业环境中,他们既要在白热化的市场竞争中开拓创新、引领企业突破发展瓶颈,又需应对来自父辈管理层的经
    华尔街科技眼 2025-05-06 18:17 28浏览
  • 这款无线入耳式蓝牙耳机是长这个样子的,如下图。侧面特写,如下图。充电接口来个特写,用的是卡座卡在PCB板子上的,上下夹紧PCB的正负极,如下图。撬开耳机喇叭盖子,如下图。精致的喇叭(HY),如下图。喇叭是由电学产生声学的,具体结构如下图。电池包(AFS 451012  21 12),用黄色耐高温胶带进行包裹(安规需求),加强隔离绝缘的,如下图。451012是电池包的型号,聚合物锂电池+3.7V 35mAh,详细如下图。电路板是怎么拿出来的呢,剪断喇叭和电池包的连接线,底部抽出PCB板子
    liweicheng 2025-05-06 22:58 602浏览
  • 文/郭楚妤编辑/cc孙聪颖‍相较于一众措辞谨慎、毫无掌舵者个人风格的上市公司财报,利亚德的财报显得尤为另类。利亚德光电集团成立于1995年,是一家以LED显示、液晶显示产品设计、生产、销售及服务为主业的高新技术企业。自2016年年报起,无论业绩优劣,董事长李军每年都会在财报末尾附上一首七言打油诗,抒发其对公司当年业绩的感悟。从“三年翻番顺大势”“智能显示我第一”“披荆斩棘幸从容”等词句中,不难窥见李军的雄心壮志。2012年,利亚德(300296.SZ)在深交所创业板上市。成立以来,该公司在细分领
    华尔街科技眼 2025-05-07 19:25 413浏览
  • UNISOC Miracle Gaming奇迹手游引擎亮点:• 高帧稳帧:支持《王者荣耀》等主流手游90帧高画质模式,连续丢帧率最高降低85%;• 丝滑操控:游戏冷启动速度提升50%,《和平精英》开镜开枪操作延迟降低80%;• 极速网络:专属游戏网络引擎,使《王者荣耀》平均延迟降低80%;• 智感语音:与腾讯GVoice联合,弱网环境仍能保持清晰通话;• 超高画质:游戏画质增强、超级HDR画质、游戏超分技术,优化游戏视效。全球手游市场规模日益壮大,游戏玩家对极致体验的追求愈发苛刻。紫光展锐全新U
    紫光展锐 2025-05-07 17:07 316浏览
  • 飞凌嵌入式作为龙芯合作伙伴,隆重推出FET-2K0300i-S全国产自主可控工业级核心板!FET-2K0300i-S核心板基于龙芯2K0300i工业级处理器开发设计,集成1个64位LA264处理器,主频1GHz,提供高效的计算能力;支持硬件ECC;2K0300i还具备丰富的连接接口USB、SDIO、UART、SPI、CAN-FD、Ethernet、ADC等一应俱全,龙芯2K0300i支持四路CAN-FD接口,具备良好的可靠性、实时性和灵活性,可满足用户多路CAN需求。除性价比超高的国产处理器外,
    飞凌嵌入式 2025-05-07 11:54 87浏览
  • 硅二极管温度传感器是一种基于硅半导体材料特性的测温装置,其核心原理是利用硅二极管的电学参数(如正向压降或电阻)随温度变化的特性实现温度检测。以下是其工作原理、技术特点及典型应用:一、工作原理1、‌PN结温度特性‌硅二极管由PN结构成,当温度变化时,其正向电压 VF与温度呈线性负相关关系。例如,温度每升高1℃,VF约下降2 mV。2、‌电压—温度关系‌通过jing确测量正向电压的微小变化,可推算出环境温度值。部分型号(如SI410)在宽温域内(如1.4 K至475 K)仍能保持高线性度。
    锦正茂科技 2025-05-09 13:52 215浏览
  • 温度传感器的工作原理依据其类型可分为以下几种主要形式:一、热电阻温度传感器利用金属或半导体材料的电阻值随温度变化的特性实现测温:l ‌金属热电阻‌(如铂电阻 Pt100、Pt1000):高温下电阻值呈线性增长,稳定性高,适用于工业精密测温。l ‌热敏电阻‌(NTC/PTC):NTC 热敏电阻阻值随温度升高而下降,PTC 则相反;灵敏度高但线性范围较窄,常用于电子设备温控。二、热电偶传感器基于‌塞贝克效应‌(Seebeck effect):两种不同
    锦正茂科技 2025-05-09 13:31 208浏览
  • Matter协议是一个由Amazon Alexa、Apple HomeKit、Google Home和Samsung SmartThings等全球科技巨头与CSA联盟共同制定的开放性标准,它就像一份“共生契约”,能让原本相互独立的家居生态在应用层上握手共存,同时它并非另起炉灶,而是以IP(互联网协议)为基础框架,将不同通信协议下的家居设备统一到同一套“语义规则”之下。作为应用层上的互通标准,Matter协议正在重新定义智能家居行业的运行逻辑,它不仅能向下屏蔽家居设备制造商的生态和系统,让设备、平
    华普微HOPERF 2025-05-08 11:40 348浏览
  • 在过去的很长一段时间里,外卖市场呈现出美团和饿了么双寡头垄断的局面。美团凭借先发优势、强大的地推团队以及精细化的运营策略,在市场份额上长期占据领先地位。数据显示,截至2024年上半年,美团外卖以68.2%的市场份额领跑外卖行业,成为当之无愧的行业老大。其业务广泛覆盖,从一线城市的繁华商圈到二三线城市的大街小巷,几乎无处不在,为无数消费者提供便捷的外卖服务。饿了么作为阿里本地生活服务的重要一环,依托阿里强大的资金和技术支持,也在市场中站稳脚跟,以25.4%的份额位居第二。尽管市场份额上与美团有一定
    用户1742991715177 2025-05-06 19:43 98浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦