你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 2788|回复: 0

[STM32L4+] [Nucleo-L4R5]学习下用LL库点灯

[复制链接]

60

主题

2051

回帖

31

蝴蝶豆

版主

最后登录
2020-12-9
发表于 2018-1-6 21:30:23 | 显示全部楼层 |阅读模式


       对于官方的STM32开发库,除了主推的HAL库之外还有一个LL(Low Layer)库,在下载的HAL开发包里面HAL库和LL库在一起共存着,LL库更接近硬件层,对于简单的外设可以直接使用,操作类似直接操作寄存器。LL库可以独立使用也可以和HAL一起混合使用,没有接触过的同学可以参考官方的例子,基本包含了各个外设的使用demo。记得前几年刚推出的时候用过一次后来也就没再玩过了,今天再再点个灯熟悉下LL库。
TIM截图20180106202918.png
外设使用例子
TIM截图20180106202938.png
LL库的特点是将很多外设的操作都封装成强制内联函数(static inline),这样的好处就是运行的效率更高,类似一种空间换时间的方案。
比如stm32l4xx_ll_bus.h中外设时钟初始化代码如下:
  1. __STATIC_INLINE void LL_AHB2_GRP1_EnableClock(uint32_t Periphs)
  2. {
  3.   __IO uint32_t tmpreg;
  4.   SET_BIT(RCC->AHB2ENR, Periphs);
  5.   /* Delay after an RCC peripheral clock enabling */
  6.   tmpreg = READ_BIT(RCC->AHB2ENR, Periphs);
  7.   (void)tmpreg;
  8. }
复制代码
除了大量的封装在外设头文件(stm32l4xx_ll_xx.h)中内联函数外,LL库对应的外设的模块驱动里面也提供了类似HAL库的初始化函数,但是内部实现还是调用的内联函数。比如下面的的IO口初始化函数
  1. ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
  2. {
  3.   uint32_t pinpos     = 0x00000000U;
  4.   uint32_t currentpin = 0x00000000U;

  5.   /* Check the parameters */
  6.   assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
  7.   assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));
  8.   assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
  9.   assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));

  10.   /* ------------------------- Configure the port pins ---------------- */
  11.   /* Initialize  pinpos on first pin set */
  12.   pinpos = POSITION_VAL(GPIO_InitStruct->Pin);

  13.   /* Configure the port pins */
  14.   while (((GPIO_InitStruct->Pin) >> pinpos) != 0x00000000U)
  15.   {
  16.     /* Get current io position */
  17.     currentpin = (GPIO_InitStruct->Pin) & (0x00000001U << pinpos);

  18.     if (currentpin)
  19.     {
  20.       /* Pin Mode configuration */
  21.       LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);

  22.       if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
  23.       {
  24.         /* Check Speed mode parameters */
  25.         assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));

  26.         /* Speed mode configuration */
  27.         LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed);
  28.       }

  29.       /* Pull-up Pull down resistor configuration*/
  30.       LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);

  31.       if (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE)
  32.       {
  33.         /* Check Alternate parameter */
  34.         assert_param(IS_LL_GPIO_ALTERNATE(GPIO_InitStruct->Alternate));

  35.         /* Speed mode configuration */
  36.         if (POSITION_VAL(currentpin) < 0x00000008U)
  37.         {
  38.           LL_GPIO_SetAFPin_0_7(GPIOx, currentpin, GPIO_InitStruct->Alternate);
  39.         }
  40.         else
  41.         {
  42.           LL_GPIO_SetAFPin_8_15(GPIOx, currentpin, GPIO_InitStruct->Alternate);
  43.         }
  44.       }
  45.     }
  46.     pinpos++;
  47.   }

  48.   if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
  49.   {
  50.     /* Check Output mode parameters */
  51.     assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));

  52.     /* Output mode configuration*/
  53.     LL_GPIO_SetPinOutputType(GPIOx, GPIO_InitStruct->Pin, GPIO_InitStruct->OutputType);

  54.   }
  55.   return (SUCCESS);
  56. }
复制代码
如果我们只使用LL库封装的内联函数的,只需要在工程里面加入一个 UTILS LL module driver.的C文件,这个文件主要是对应系统时钟的一些处理,其他的设置都可以使用头文件里面封装内联函数实现。
TIM截图20180106210440.png
1、点灯
类似寄存器操作,点灯就是初始化IO口的时钟,然后设置对应的IO输出模式即可,其他的速度和上下拉也可以一步一步设置
  1. void LED_Init(void)
  2. {
  3.   /* Enable the LED Clock */
  4.   LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
  5.   LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);


  6.   LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);
  7.   LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_14, LL_GPIO_MODE_OUTPUT);
  8.   LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);

  9. }
复制代码
闪烁LED 如下:都在使用的内联函数
  1. void LED_Blinking(void)
  2. {  

  3.   LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_7 | LL_GPIO_PIN_14);  
  4.   LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_7 );

  5. }
复制代码

2、串口输出
熟悉了LED初始化之后再来看下串口的,首先是对应的IO口的初始化
  1. LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOG);

  2.   
  3.   LL_GPIO_SetPinMode(GPIOG, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);
  4.   LL_GPIO_SetAFPin_0_7(GPIOG, LL_GPIO_PIN_7, LL_GPIO_AF_8);
  5.   LL_GPIO_SetPinSpeed(GPIOG, LL_GPIO_PIN_7, LL_GPIO_SPEED_FREQ_HIGH);
  6.   LL_GPIO_SetPinOutputType(GPIOG, LL_GPIO_PIN_7, LL_GPIO_OUTPUT_PUSHPULL);
  7.   LL_GPIO_SetPinPull(GPIOG, LL_GPIO_PIN_7, LL_GPIO_PULL_UP);


  8.   LL_GPIO_SetPinMode(GPIOG, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
  9.   LL_GPIO_SetAFPin_8_15(GPIOG, LL_GPIO_PIN_8, LL_GPIO_AF_8);
  10.   LL_GPIO_SetPinSpeed(GPIOG, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);
  11.   LL_GPIO_SetPinOutputType(GPIOG, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_PUSHPULL);
  12.   LL_GPIO_SetPinPull(GPIOG, LL_GPIO_PIN_8, LL_GPIO_PULL_UP);
复制代码
然后是时钟源的初始化
  1. /* (2) Enable USART peripheral clock and clock source ***********************/
  2.   
  3.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  4.   LL_PWR_EnableVddIO2();
  5.   
  6.   LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
  7.   
  8.   /* HSI configuration and activation */
  9.   LL_RCC_HSI_Enable();
  10.   while(LL_RCC_HSI_IsReady() != 1)
  11.   {
  12.   };
  13.   
  14.   /* Set clock source */  
  15.   LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_HSI);
复制代码
最后就是串口的的参数设置和使能了
  1. /* TX/RX direction */
  2.   LL_LPUART_SetTransferDirection(LPUART1, LL_LPUART_DIRECTION_TX_RX);

  3.   /* 8 data bit, 1 start bit, 1 stop bit, no parity */
  4.   LL_LPUART_ConfigCharacter(LPUART1, LL_LPUART_DATAWIDTH_8B, LL_LPUART_PARITY_NONE, LL_LPUART_STOPBITS_1);

  5.   /* No Hardware Flow control */
  6.   /* Reset value is LL_USART_HWCONTROL_NONE */
  7.   // LL_USART_SetHWFlowCtrl(LPUART1, LL_USART_HWCONTROL_NONE);

  8.   /* Set Baudrate to 9600 using HSI frequency set to HSI_VALUE */
  9.   LL_LPUART_SetBaudRate(LPUART1, HSI_VALUE,LL_LPUART_PRESCALER_DIV1, 9600);

  10.   /* Enable LPUART1 **********************************************************/
  11.   LL_LPUART_Enable(LPUART1);
复制代码
大致的套路和寄存器有点类似,想要使用LL库要对外设的各个初始化流程比较熟悉,没有接触过的可以先参考官方提供的例子。
最后是mian函数
  1. int main(void)
  2. {  
  3.   SystemClock_Config();  
  4.   LPUART1_Init();   
  5.   LED_Init();  
  6.   while (1)
  7.   {
  8.     LED_Blinking();
  9.     printf("Hi,I am creep!!!\n");
  10.     LL_mDelay(1000);
  11.   }
  12. }

复制代码
下载之后可以看到LED闪烁及串口输出如下:
TIM截图20171231115407.png

测试代码:
IAR-LED-LL.rar (5.82 MB, 下载次数: 36)
回复

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版