|
从寄存器操作到硬件抽象层:STM32开发库的演进。 演进历程STM32微控制器自2007年推出以来,STMicroelectronics为其提供了多套软件开发库,经历了从直接寄存器操作到高度抽象化的演进过程: 发展时间线
抽象层次中等高低 代码体积中等大小 执行效率高中等高- f1 e' C* L. @5 p9 P" \# |3 b3 S 学习难度中等低高/ m6 `3 o( V7 \# O S 可移植性低高中等3 r8 c I. O2 U3 P5 w) c+ D- O 维护状态已停止活跃活跃 工具支持无CubeMXCubeMX标准外设库(SPL)设计理念 SPL采用"一个外设一个文件"的设计理念,每个外设都有对应的.c和.h文件,提供中等层次的抽象。 核心特点// SPL典型用法示例void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;3 A* S: i0 W1 d6 f // 使能GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/ F1 d I; X+ j' O. f+ ^9 ^) v2 Z // 配置GPIO5 f. K) T/ T; \$ |7 B1 @' ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;$ p! h# Z. A/ n' F6 ~ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;2 o1 ?7 P5 m F: B9 |0 } GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); }优势
HAL库采用"硬件抽象层"设计,旨在提供跨系列的统一API接口,隐藏硬件细节。 核心特点// HAL库典型用法示例void GPIO_Config(void)3 t( {; ~2 A0 t! [ { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIO时钟 __HAL_RCC_GPIOA_CLK_ENABLE();& C0 i, p0 D" P8 L // 配置GPIO GPIO_InitStruct.Pin = GPIO_PIN_5;6 [! S. D! W0 g GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL;+ o2 X7 }. u% K# b3 B GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); }架构优势
LL库是HAL库的补充,提供更接近硬件的接口,同时保持一定的可移植性。 核心特点// LL库典型用法示例8 b# c. }- M& {9 D3 j2 J svoid GPIO_Config(void)0 b0 x$ Y% o" }+ @# a { // 使能GPIO时钟 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);( N0 f. m7 m& r; m. W' R9 J$ F8 \ LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_5, LL_GPIO_SPEED_FREQ_HIGH); }优势
{) C. q7 K4 C: y* \; V) m G7 t USART_InitTypeDef USART_InitStructure;2 n3 L1 ^1 K( Z4 I d: j9 } GPIO_InitTypeDef GPIO_InitStructure;2 B$ P& s9 I0 ^0 e' _; Q // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);3 l W. U% k/ ? i- m( C: _ // 配置GPIO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX% V$ E! ^% K9 A GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);6 ?2 `2 v( B n& k GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX* o, l+ k9 T" R2 K GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;' u0 {4 j6 t# m$ i& z6 P1 d GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置UART/ p! U% Z" }7 P: t9 v3 x# W) k- \ USART_InitStructure.USART_BaudRate = 115200;& F: c2 T; d' } u0 w USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1;3 s d1 E* A8 t1 T& \ USART_InitStructure.USART_Parity = USART_Parity_No;0 K0 e4 n9 j+ X9 f( t USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure);0 {( f% m1 O8 r1 ^5 j USART_Cmd(USART1, ENABLE); } % e& l1 U- z9 \0 V+ A& ` voidUART_SendString(char* str)6 Q2 T* y6 @. D- ~3 w/ o6 @% z { while(*str) { while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);. Q7 }/ D/ M9 L/ ~4 v1 F) ^% G USART_SendData(USART1, *str++); N: k3 x7 C7 E8 e) G } }HAL方式void UART_Config(void)- A' K7 W8 M9 Y% K8 }1 t1 ^0 J { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能时钟 __HAL_RCC_USART1_CLK_ENABLE();6 ^, \; d& Q, h __HAL_RCC_GPIOA_CLK_ENABLE();" A5 |$ k) }$ n% r // 配置GPIO8 ?- g% O+ G! ?6 w" Q) W9 E GPIO_InitStruct.Pin = GPIO_PIN_9;8 k& x* v* Y! ^3 {0 e% q. d# e GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;' ]. O2 K$ O3 X: l2 |2 a' \ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10;0 d& g. H: q" N- U GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;3 n7 I w# O6 j. n HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);* R' ~% h) `5 U) W // 配置UART huart1.Instance = USART1;. V+ r5 ]& W. p huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B;( S% u/ @8 X% @6 P huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16;( C r0 S: b8 t( p HAL_UART_Init(&huart1);8 {# b: ?; D. \$ {3 q8 m }: Z& _( D; @- P. T voidUART_SendString(char* str). y9 l2 c/ o0 H; i$ R {) Q0 P+ u! S6 F E8 N3 P HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), HAL_MAX_DELAY); }LL方式void UART_Config(void) { // 使能时钟' m1 ]# t( n. ], X) t LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);/ A/ D/ Q# j) C: @3 k# Z LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); ' I+ i% f/ Z2 I- H P. L // 配置GPIO LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);5 I, [1 R$ t5 X0 u; b LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_9, LL_GPIO_AF_7); LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);, ^( s& s( w1 ~" V. L" j LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_10, LL_GPIO_AF_7); % q, f5 e( r8 Y! H- f9 R0 s // 配置UART+ h& H* i: u, y+ v { LL_USART_SetBaudRate(USART1, 115200); LL_USART_SetDataWidth(USART1, LL_USART_DATAWIDTH_8B); LL_USART_SetStopBitsLength(USART1, LL_USART_STOPBITS_1); LL_USART_SetParity(USART1, LL_USART_PARITY_NONE);: S( c- u+ c6 l. Y! ^3 W LL_USART_SetTransferDirection(USART1, LL_USART_DIRECTION_TX_RX); LL_USART_Enable(USART1); } voidUART_SendString(char* str)& H" h2 E( P$ [) n7 O( _& E { while(*str) { while(!LL_USART_IsActiveFlag_TXE(USART1));; d5 G: Q& h* N- E: y9 G* I6 D$ i LL_USART_TransmitData8(USART1, *str++); } } " d9 I- z) d& S* u9 C- K' j |
#双节活动 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开发之环境空气质量监测
微信公众号
手机版