STM32LL库学习日志(1)点灯
为什么是LL
我是首次学习STM32,虽然之前有大致的了解但总是没有开始。我开始学之前大致了解了一下:
- ST 做了一个叫STM32CubeMX的东西,用于自动生成STM32的配置代码,它支持HAL库和LL库,不支持标准库。
- 据说HAL库被做的性能不好,于是后来开发了LL库。
- LL库是做为HAL库的补充,可以与HAL库混用。
显而易见啊,我这么懒,肯定标准库劝退啊,肯定选HAL和LL;其次Keil的编辑器有点丑,我之前做视觉习惯用Clion,所以就按网上配了一套gcc-arm-none-eadi + OpenOCD的ToolChain(其实Keil自己改一下也还不错);LL库性能更好,所以选LL库,当然,必须要用HAL库的时候,还是用HAL库。
库结构
LL库作为HAL库的补充,源文件和HAL放在一起,进目录看LL库的文件,的确是一个补充,文件数量少了一半,有一些外设是没有LL实现的,但是作为新手,简单的外设用LL完全没有问题。
我的编译器
昨天更新CubeMX的时候被官方告知了未来将不支持此工具链了。(我没事更啥新呢)
所以在文章中与编译环境相关的东西不会出现。编译环境与CubeMX的代码生成设置一样就好。
开始!!点灯!!
开发平台
单片机:野火STM32F103VET6(指南者)
STM32CubeMX版本:6.3.0
CubeMX生成代码
其他文章有,不赘述了,和HAL库的一样,就是在Project Manager的Advanced Settings里把你想用LL库的外设改成LL库的就行。
实验硬件
我的板子上LED灯在GPIOB的0、1、5,分别是绿、蓝、红色灯(在一个灯里有三个灯珠,好高级的样子)
“灯大、灯亮、灯会闪”要做什么
我们要点灯自然要看GPIO库,根据HAL库的教程,点灯分几步:
- 初始化GPIO
- 置高/置低/翻转 GPIO
看看库里有什么
初始化结构体 LL_GPIO_InitTypeDef
/**
* @brief LL GPIO Init Structure definition
*/
typedef struct
{
uint32_t Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_LL_EC_PIN */
uint32_t Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIO_LL_EC_MODE.
GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinMode().*/
uint32_t Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIO_LL_EC_SPEED.
GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinSpeed().*/
uint32_t OutputType; /*!< Specifies the operating output type for the selected pins.
This parameter can be a value of @ref GPIO_LL_EC_OUTPUT.
GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinOutputType().*/
uint32_t Pull; /*!< Specifies the operating Pull-up/Pull down for the selected pins.
This parameter can be a value of @ref GPIO_LL_EC_PULL.
GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinPull().*/
} LL_GPIO_InitTypeDef;
Pin宏
#define LL_GPIO_PIN_0 ((GPIO_BSRR_BS0 << GPIO_PIN_MASK_POS) | 0x00000001U) /*!< Select pin 0 */
#define LL_GPIO_PIN_1 ((GPIO_BSRR_BS1 << GPIO_PIN_MASK_POS) | 0x00000002U) /*!< Select pin 1 */
#define LL_GPIO_PIN_2 ((GPIO_BSRR_BS2 << GPIO_PIN_MASK_POS) | 0x00000004U) /*!< Select pin 2 */
#define LL_GPIO_PIN_3 ((GPIO_BSRR_BS3 << GPIO_PIN_MASK_POS) | 0x00000008U) /*!< Select pin 3 */
#define LL_GPIO_PIN_4 ((GPIO_BSRR_BS4 << GPIO_PIN_MASK_POS) | 0x00000010U) /*!< Select pin 4 */
#define LL_GPIO_PIN_5 ((GPIO_BSRR_BS5 << GPIO_PIN_MASK_POS) | 0x00000020U) /*!< Select pin 5 */
#define LL_GPIO_PIN_6 ((GPIO_BSRR_BS6 << GPIO_PIN_MASK_POS) | 0x00000040U) /*!< Select pin 6 */
#define LL_GPIO_PIN_7 ((GPIO_BSRR_BS7 << GPIO_PIN_MASK_POS) | 0x00000080U) /*!< Select pin 7 */
#define LL_GPIO_PIN_8 ((GPIO_BSRR_BS8 << GPIO_PIN_MASK_POS) | 0x04000001U) /*!< Select pin 8 */
#define LL_GPIO_PIN_9 ((GPIO_BSRR_BS9 << GPIO_PIN_MASK_POS) | 0x04000002U) /*!< Select pin 9 */
#define LL_GPIO_PIN_10 ((GPIO_BSRR_BS10 << GPIO_PIN_MASK_POS) | 0x04000004U) /*!< Select pin 10 */
#define LL_GPIO_PIN_11 ((GPIO_BSRR_BS11 << GPIO_PIN_MASK_POS) | 0x04000008U) /*!< Select pin 11 */
#define LL_GPIO_PIN_12 ((GPIO_BSRR_BS12 << GPIO_PIN_MASK_POS) | 0x04000010U) /*!< Select pin 12 */
#define LL_GPIO_PIN_13 ((GPIO_BSRR_BS13 << GPIO_PIN_MASK_POS) | 0x04000020U) /*!< Select pin 13 */
#define LL_GPIO_PIN_14 ((GPIO_BSRR_BS14 << GPIO_PIN_MASK_POS) | 0x04000040U) /*!< Select pin 14 */
#define LL_GPIO_PIN_15 ((GPIO_BSRR_BS15 << GPIO_PIN_MASK_POS) | 0x04000080U) /*!< Select pin 15 */
#define LL_GPIO_PIN_ALL (LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | \
LL_GPIO_PIN_3 | LL_GPIO_PIN_4 | LL_GPIO_PIN_5 | \
LL_GPIO_PIN_6 | LL_GPIO_PIN_7 | LL_GPIO_PIN_8 | \
LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11 | \
LL_GPIO_PIN_12 | LL_GPIO_PIN_13 | LL_GPIO_PIN_14 | \
LL_GPIO_PIN_15) /*!< Select all pins */
主要相关函数
__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask); //对GPIOx的PinMask引脚置高电平(多引脚用或连接)
__STATIC_INLINE void LL_GPIO_ResetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask); //对GPIOx的PinMask引脚置低电平
__STATIC_INLINE void LL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint32_t PinMask); //翻转GPIOx的PinMask引脚置电平
__STATIC_INLINE void LL_GPIO_WriteOutputPort(GPIO_TypeDef *GPIOx, uint32_t PortValue);//对GPIOx的所有引脚赋值
实验主要代码
int main() {
/* Some initial code*/
Init();
/* infinite loop*/
while (1) {
//Toggle Pin0 by set and reset function
LL_GPIO_SetOutputpin(GPIOB, LL_GPIO_PIN_0);
LL_mDelay(500);
LL_GPIO_ResetOutputpin(GPIOB, LL_GPIO_PIN_0);
LL_mDelay(500);
//Toggle Pin1 by toggle function
LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_1);
LL_mDelay(500);
}
原理
打开源文件stm32f1xx_ll_gpio.c
可以看到函数的源码
__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
WRITE_REG(GPIOx->BSRR, (PinMask >> GPIO_PIN_MASK_POS) & 0x0000FFFFU);
}
可以看到LL是写寄存器操作