电子产业一站式赋能平台

PCB联盟网

搜索
查看: 217|回复: 0
收起左侧

寄存器开发,HAL开发和LL开发的区别和参考代码

[复制链接]

397

主题

397

帖子

2461

积分

三级会员

Rank: 3Rank: 3

积分
2461
发表于 2023-11-16 21:01:00 | 显示全部楼层 |阅读模式

t53d3wzz23x64077266428.png

t53d3wzz23x64077266428.png

( j5 _* @! R5 n8 s# u1 L, J( m0 h4 A6 Q4 y$ S1 ?. o: U5 O
1,寄存器开发【难度值:难】
: ?( \' P1 n# T# ]$ m寄存器开发是一种直接访问微控制器寄存器的编程方法,它提供了对硬件的极大灵活性和直接控制。在寄存器级开发中,程序员通过直接写入和读取寄存器来配置和控制微控制器的外设,而不依赖高级的抽象层。7 ?6 C! v- F" b1 Q. A4 X" Z
以下是寄存器级开发的一般步骤和示例:1. 包含头文件在程序中包含与目标微控制器系列相关的寄存器定义头文件。
  • #include "stm32f4xx.h"5 v* I  b( [4 H/ q& [/ Q
    2. 初始化时钟配置系统时钟和外设时钟。
  • // 配置系统时钟RCC->CR |= RCC_CR_HSEON;  // 启动外部高速时钟// 等待HSE稳定while (!(RCC->CR & RCC_CR_HSERDY)) {}RCC->CFGR |= RCC_CFGR_SW_HSE;  // 切换系统时钟到HSE, J$ G7 v  a( Q, m
    3. 配置外设直接写入外设寄存器进行配置。例如,配置GPIO引脚:
  • // 配置GPIO引脚GPIOA->MODER |= GPIO_MODER_MODER5_0;  // 将引脚5配置为通用输出模式GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5;   // 将引脚5配置为推挽输出          % P1 ^; R9 \4 l: @; z# m# F
    4. 中断处理如果使用中断,配置和实现中断处理函数。例如,配置USART中断:
  • // 配置USART中断NVIC_SetPriority(USART1_IRQn, 0);NVIC_EnableIRQ(USART1_IRQn);
    ' P/ f, _+ r5 Q5. 主循环在主循环中进行任务处理。例如,使用USART进行通信:
  • while (1) {  // 等待发送缓冲区就绪  while (!(USART1->SR & USART_SR_TXE)) {}  // 发送数据  USART1->DR = data_to_send;  // 等待接收缓冲区非空  while (!(USART1->SR & USART_SR_RXNE)) {}  // 接收数据  received_data = USART1->DR;}在寄存器级开发中,程序员需要仔细阅读芯片手册和寄存器定义,了解寄存器的功能和配置方式。这样做的好处是可以对硬件有更直接的控制,但同时也需要更多的了解和小心处理硬件细节。/ R8 O2 ?  }' e* R3 K
    2,HAL库开发【难度值:易】当使用HAL库进行开发时,主要是通过调用HAL库提供的函数来配置和控制STM32微控制器的外设。HAL库旨在提供一种跨STM32系列通用的接口,使得开发者可以以相对高层次的抽象水平来进行开发,而不必深入了解底层硬件的细节。
    $ t1 `3 W- N$ P; Z) L+ q( f' `以下是使用HAL库进行开发的一般步骤:   1. 初始化:在程序的开始阶段,通常会调用 `HAL_Init()` 来初始化HAL库。这个函数执行一些底层的初始化工作,包括设置系统时钟。
  • HAL_Init();         
    5 @& n! \, U3 b: K/ N$ F5 ~  C9 S& s2. 系统时钟配置:使用 `HAL_RCC_ClockConfig()` 等函数来配置系统时钟。这涉及到选择和配置时钟源、设置分频器等。
  • // 配置系统时钟为最大频率 HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);         
    + e; B; C) `9 `7 u' Y5 f& y3. 外设初始化对需要使用的外设进行初始化。这通常涉及使用 `HAL_InitTick()` 和 `HAL_MspInit()` 等函数来初始化一些必要的外设和中断。
    - i0 t6 u: d% j2 V* s+ V0 a
  • // 初始化系统滴答定时器HAL_InitTick(TICK_INT_PRIORITY);          0 z' I' M4 a- b9 @* p. Q" r
    4. 外设配置使用HAL库提供的配置函数,例如 `HAL_UART_Init()`、`HAL_GPIO_Init()` 等,对外设进行配置。   
  • // 配置UARTUART_HandleTypeDef uart;uart.Instance = USART1;uart.Init.BaudRate = 115200;uart.Init.WordLength = UART_WORDLENGTH_8B;uart.Init.StopBits = UART_STOPBITS_1;uart.Init.Parity = UART_PARITY_NONE;uart.Init.Mode = UART_MODE_TX_RX;uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;uart.Init.OverSampling = UART_OVERSAMPLING_16;HAL_UART_Init(&uart);          / L- Y3 r, `. }* G# H& W
    5. 中断处理如果使用中断,需要配置和实现相应的中断处理函数。HAL库提供了 `HAL_NVIC_SetPriority()` 等函数来配置中断优先级。
  •     // 配置USART中断    HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);    HAL_NVIC_EnableIRQ(USART1_IRQn);         
    0 ?0 J" X, `7 ~) u0 D6. 主循环在主循环中处理任务。通常使用 `HAL_UART_Transmit()`、`HAL_UART_Receive()` 等函数来进行通信。
  • while (1)   {    // 接收数据    HAL_UART_Receive(&uart, rx_buffer, 1, HAL_MAX_DELAY);    // 处理数据        // 发送数据    HAL_UART_Transmit(&uart, tx_buffer, sizeof(tx_buffer), HAL_MAX_DELAY);  }8 I+ `$ E' m( Y% C( c+ L
    以上是使用HAL库进行STM32开发的一般步骤。HAL库提供了大量的函数和抽象,使得开发者能够相对轻松地进行STM32微控制器的开发,而不必深入研究底层硬件的复杂性。       3,LL库开发【难度值:中】   LL库是HAL库的底层实现,提供了对STM32微控制器的底层寄存器级别的直接访问。LL库是HAL库的一部分,它的目标是提供对硬件的底层控制,同时保持相对较高的可移植性。          以下是使用LL库进行开发的一般步骤和示例:1.包含头文件在程序中包含LL库相关的头文件。
  •     #include "stm32f4xx_ll_gpio.h"    #include "stm32f4xx_ll_rcc.h"
    ; P; q5 L4 j' L4 ^3 B8 ~2. 初始化时钟配置系统时钟和外设时钟。
  •     LL_Init1msTick(SystemcoreClock);    LL_SYSTICK_EnableIT();
    $ ]0 M5 K* Y( w0 ?: Q$ c3.配置外设直接写入寄存器进行配置。例如,配置GPIO引脚:
  •     // 配置GPIO引脚        LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);    LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);    LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_5, LL_GPIO_SPEED_FREQ_LOW);8 j, K5 e0 ]9 u4 Q! r
    4.中断处理如果使用中断,配置和实现中断处理函数。例如,配置USART中断:
  •     // 配置USART中断    NVIC_SetPriority(USART1_IRQn, 0);    NVIC_EnableIRQ(USART1_IRQn);
    6 ?( G" H: E' Z3 ?9 `. E+ a5. 主循环6 k  Z6 X, y# p; M8 Q6 t
    在主循环中进行任务处理。例如,使用USART进行通信:
    7 v, ]9 |  d$ d# @# K' r
  •     while (1) {        // 发送数据        while (!LL_USART_IsActiveFlag_TXE(USART1)) {}        LL_USART_TransmitData8(USART1, data_to_send);( X; W* f: h8 y+ N8 b7 a3 {, R- ?
            // 等待接收数据        while (!LL_USART_IsActiveFlag_RXNE(USART1)) {}        received_data = LL_USART_ReceiveData8(USART1);    }( N; p. Q" p+ }
    使用LL库进行开发相对于使用寄存器级别的开发提供了更高的抽象层次,但仍然直接操作硬件寄存器。这使得LL库的使用更加直观,同时保持了相对较高的性能。+ \/ v3 \- P9 C8 {
              总的来说,新手推荐学习HAL,因为简单,网上资料也多,等对HAL有一定的基础之后,再学习LL库,LL库是直接操作寄存器的,代码比较精简,运行效率比较高,也是一种趋势。寄存器现在完全不推荐,因为ST官方都放弃了。   
    - w% z, i; i* @+ w+ O
    / H$ c* a+ ~, M1 j==========5 J7 [2 i- G& U# K- `6 R2 L2 `1 b
    往期回顾:KEIL 开发技巧; ?3 s, I$ R/ X3 B8 v6 S4 y" o
    大学生学嵌入式的三个阶段
    # G' g0 b7 L# g# x2个器件,做1个恒流源
    3 M3 N1 w# y+ M8 R( R) Z9 B/ M一个MOS管制作成开关电路
    . f0 x% P9 e! J$ d; cSTM32项目版本管理方法& @7 `% F3 a, U7 s' n- G
    ==========3 O8 M& l  M+ ^) R- H- s1 j

    mwtz1euimvr64077266528.png

    mwtz1euimvr64077266528.png

    9 t8 I7 s) p1 C( S
    % w& Z) P% Y* z5 z
    : j1 }1 C; V4 _* }) r. D

    gxj1ljazcst64077266628.png

    gxj1ljazcst64077266628.png
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表