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

查看: 2730|回复: 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管理
行使您的权利
官方最新发布
13245底部标题123相同标题
12底部标题123相同标题
33333底部标题123相同序号
3435底部标题-无链接
关注我们
st-img 微信公众号
st-img 手机版