|
从寄存器操作到硬件抽象层:STM32开发库的演进。 演进历程STM32微控制器自2007年推出以来,STMicroelectronics为其提供了多套软件开发库,经历了从直接寄存器操作到高度抽象化的演进过程: 发展时间线
抽象层次中等高低* K+ ]" v6 y8 i2 _5 n" q! J 代码体积中等大小 执行效率高中等高 学习难度中等低高 可移植性低高中等1 f7 O/ ~/ I* X; t& q 维护状态已停止活跃活跃7 Z4 e% X: v. ~9 P 工具支持无CubeMXCubeMX标准外设库(SPL)设计理念 SPL采用"一个外设一个文件"的设计理念,每个外设都有对应的.c和.h文件,提供中等层次的抽象。 核心特点// SPL典型用法示例void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; " W8 {- Y) [$ e/ i0 j2 o$ w // 使能GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); : \3 F/ H2 z9 x, l4 C( v6 N$ E' w // 配置GPIO0 a! b; y) ] p6 T$ _( [ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;$ i: U, z6 ~* E5 b6 d [ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);' C/ B- X% H S' M( e( ?$ S( x4 f }优势
HAL库采用"硬件抽象层"设计,旨在提供跨系列的统一API接口,隐藏硬件细节。 核心特点// HAL库典型用法示例: A: J* y! a1 R vvoid GPIO_Config(void). |2 y- w6 b% M6 e* w5 W% i {/ C4 X5 I9 a6 ^8 J3 ^/ |- S GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIO时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); 2 O& ^) N- q, i: V" H // 配置GPIO GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;2 U0 w" |, D' a' r HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); }架构优势
LL库是HAL库的补充,提供更接近硬件的接口,同时保持一定的可移植性。 核心特点// LL库典型用法示例1 Z& i |) K6 o7 y0 X0 jvoid GPIO_Config(void) { // 使能GPIO时钟, L6 ^' ]4 p( @ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); // 配置GPIO LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT); LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_5, LL_GPIO_OUTPUT_PUSHPULL); LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_5, LL_GPIO_SPEED_FREQ_HIGH);( o! \& X/ i& x/ ~6 w) G. d }优势
{* U! m2 Z; M7 {' D3 B: M' H6 a USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置GPIO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX z$ H- n& n: Z( k) G# P GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5 M) r4 |! U$ T4 d; S GPIO_Init(GPIOA, &GPIO_InitStructure);5 T) H6 p9 \7 J0 H4 G $ R* P9 b" b" Z% T! V9 p7 P5 X6 O) a3 `! k GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure);$ R w* Y: { h+ i k: B // 配置UART5 n4 i% n; ]6 p4 } USART_InitStructure.USART_BaudRate = 115200;, r/ L. S! N6 K5 {* y USART_InitStructure.USART_WordLength = USART_WordLength_8b;6 \7 D* z% A" q+ D7 |, A USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No;$ x( I+ P( q# ~" O* O: W& [& P& I USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;* ?* `* s+ a( P) e9 d USART_Init(USART1, &USART_InitStructure); ?2 t, x$ `0 \ 7 ~: }+ _) i+ w% e USART_Cmd(USART1, ENABLE); }3 _, H# B+ B7 e voidUART_SendString(char* str) {# P6 A1 j" r! T; C while(*str) {' U4 c8 |# J' c+ j4 t: O0 H2 Y while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);: c" V. ?, H* u3 x- q4 m USART_SendData(USART1, *str++); }! J( B1 e; w5 s3 a: ?+ ~, d: j( v5 K }HAL方式void UART_Config(void). y) Z6 }6 v8 J( d0 B {3 m% t, }6 ^% V9 E( h- s GPIO_InitTypeDef GPIO_InitStruct = {0};' Z/ H" \+ W. C* m8 S5 c // 使能时钟2 |' E5 X F( a* ], v1 L4 n __HAL_RCC_USART1_CLK_ENABLE();7 f6 k" T. l9 f __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置GPIO GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;7 V; ]; u5 {, M3 \. b0 R6 ?$ m) X GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;; W: a6 k" v' L HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); & x! F5 v" J4 b3 I7 Z, i9 b! L GPIO_InitStruct.Pin = GPIO_PIN_10;- G3 I+ O# b. c/ f% Z; Y) m GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ( q* ~# {9 t& V2 h* Z5 ^1 y // 配置UART; d; C$ e% d2 Q+ w; g* O huart1.Instance = USART1;% s: W! u4 Y3 ~7 y" P huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; J8 B2 K! x% f: V! n' I( } huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE;5 j( ~& y7 k* c6 q huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;+ _. G7 P: B$ f( D; F huart1.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart1);- g9 N, S4 ?4 x) i( c' p } 9 a* q# n' f4 m u" A* p: Q( `) g: J: g voidUART_SendString(char* str) {; a2 K- W; G) y! s HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), HAL_MAX_DELAY); }LL方式void UART_Config(void) {6 q0 t( _2 V. s // 使能时钟* f5 A: g3 o; D. e3 Y, ? LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);- W+ f9 ~1 d. ` // 配置GPIO LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_9, LL_GPIO_AF_7);$ `+ b; E5 w2 m( |5 Z; \- q LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH); + [8 I6 N4 b+ X' }" a5 P& ?) ~ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE);6 p" V; w: o1 l1 C! J2 M LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_10, LL_GPIO_AF_7); 7 r6 I* m3 S6 a0 K' g' I' B& J) D // 配置UART$ _! a5 T; a. e1 I. I LL_USART_SetBaudRate(USART1, 115200);! U0 _! U( A2 k4 ~1 K% W: S LL_USART_SetDataWidth(USART1, LL_USART_DATAWIDTH_8B);( c" r: @0 ^5 I LL_USART_SetStopBitsLength(USART1, LL_USART_STOPBITS_1); LL_USART_SetParity(USART1, LL_USART_PARITY_NONE); LL_USART_SetTransferDirection(USART1, LL_USART_DIRECTION_TX_RX); LL_USART_Enable(USART1);: h' A @% ?5 x" t2 e+ x }! j) T, O: u" G! t% W. a ; M( Y2 [! m0 E( e: ?% c5 T& c voidUART_SendString(char* str) { while(*str) { while(!LL_USART_IsActiveFlag_TXE(USART1));, A4 s9 \/ I9 k LL_USART_TransmitData8(USART1, *str++); }# p: e) Q- v+ R& v0 i } 9 C. Y7 D. \2 v" F0 X* W2 ? |
#双节活动 1.在CubeMX中引用touchGFX出现的问题与解决
如何将STM32CubeMX生成的CMake工程导入STM32CubeIDE
【 逢7发帖赢大礼】1、利用CubeMX生成正点原子H7R7开发板的STM32CubeIDE工程
STM32CubeCLT 1.22.0新版本发布
【下载问题解决】关于ST官网下载软件问题解决
STM32CubeMX 6.18.0新版本发布
【STM32U3评测】使用INS5699 RTC模组
CubeMX生成CubeIDE工程代码乱码
【逢7发帖赢大礼】STM32开发之指纹识别!
【逢7发帖赢大礼】STM32开发之环境空气质量监测
微信公众号
手机版