【NUCLEO-L496ZG评测】第二部 : 基于LL库 ,进行GPIO 电平翻转测试
本帖最后由 harvardx 于 2017-5-18 21:24 编辑第一篇,已经熟悉了开发环境,熟悉了最新的cubemx. STM32CubeL4 Firmware Package 已经更新到V1.8.0/ 21-April-2017,增加了 对B-L475E-IOT01 物联网开发板的支持. 对于我们使用的L496,更新了CMSIS中的
[*]stm32l496xx.h and stm32l4a6xx.h device description files
[*]FIREWALL
[*]Fix FW_VDSSA_ADD_Msk and FW_VDSL_LENG_Msk definitions
[*]TIM16
[*]Fix TIM16_OR1_TI1_RMP_Msk definitio
[*]
本篇,我们将利用LL库,实现同样的功能,这次我们的控制对象改为LD1, 我们要完成LD1的闪烁功能.
上篇,我们是直接去写端口,延时,然后再写不同电平,延时, 然后循环的思路来实现.本篇采用不同的手段实现, 直接采用d端口的toggle功能来实现. 实际上就是把当前的端口值在和1异或一下. 具体的实现在stm32L4xx_II_gpio.h
__STATIC_INLINE void LL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
WRITE_REG(GPIOx->ODR, READ_REG(GPIOx->ODR) ^ PinMask);
}
LL库的整个体系结构清晰, 效率高, 在库函数和直接寄存器操作中间找到一个合适的切入点. 对效率要求高的应用,可以 试试看LL库.
主要程序摘录如下: 按照250ms的周期间隔, 不断的反转LD1所在的电平.
/**
******************************************************************************
* @file Examples_LL/GPIO/GPIO_InfiniteLedToggling/Src/main.c
* @authorMCD Application Team
* @version V1.8.0
* @date 21-April-2017
* @brief This example describes how to configure and use GPIOs through
* the STM32L4xxGPIO LL API.
* Peripheral initialization done using LL unitary services functions.
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32L4xx_LL_Examples
* @{
*/
/** @addtogroup GPIO_InfiniteLedToggling
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Configure_GPIO(void);
/* Private functions ---------------------------------------------------------*/
/**
* @briefMain program
* @paramNone
* @retval None
*/
int main(void)
{
/* Configure the system clock to 40 MHz */
SystemClock_Config();
/* -2- Configure IO in output push-pull mode to drive external LED */
Configure_GPIO();
/* Toggle IO in an infinite loop */
while (1)
{
LL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_PIN);
/* Insert delay 250 ms */
LL_mDelay(250);
}
}
/**
* @briefThis function configures GPIO
* @note Peripheral configuration is minimal configuration from reset values.
* Thus, some useless LL unitary functions calls below are provided as
* commented examples - setting is default configuration from reset.
* @paramNone
* @retval None
*/
void Configure_GPIO(void)
{
/* Enable the LED1 Clock */
LED1_GPIO_CLK_ENABLE();
/* Configure IO in output push-pull mode to drive external LED1 */
LL_GPIO_SetPinMode(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_MODE_OUTPUT);
/* Reset value is LL_GPIO_OUTPUT_PUSHPULL */
//LL_GPIO_SetPinOutputType(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_OUTPUT_PUSHPULL);
/* Reset value is LL_GPIO_SPEED_FREQ_LOW */
//LL_GPIO_SetPinSpeed(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_SPEED_FREQ_LOW);
/* Reset value is LL_GPIO_PULL_NO */
//LL_GPIO_SetPinPull(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_PULL_NO);
}
/**
* @briefSystem Clock Configuration
* The system Clock is configured as follows :
* System Clock source = PLL (MSI)
* SYSCLK(Hz) = 40000000
* HCLK(Hz) = 40000000
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 1
* MSI Frequency(Hz) = 4000000
* PLL_M = 1
* PLL_N = 40
* PLL_R = 2
* Flash Latency(WS) = 4
* @paramNone
* @retval None
*/
void SystemClock_Config(void)
{
/* MSI configuration and activation */
LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
LL_RCC_MSI_Enable();
while(LL_RCC_MSI_IsReady() != 1)
{
};
/* Main PLL configuration and activation */
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 40, LL_RCC_PLLR_DIV_2);
LL_RCC_PLL_Enable();
LL_RCC_PLL_EnableDomain_SYS();
while(LL_RCC_PLL_IsReady() != 1)
{
};
/* Sysclk activation on the main PLL */
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
};
/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
/* Set systick to 1ms in using frequency set to 80MHz */
/* This frequency can be calculated through LL RCC macro */
/* ex: __LL_RCC_CALC_PLLCLK_FREQ(__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN, LL_RCC_MSIRANGE_6),
LL_RCC_PLLM_DIV_1, 40, LL_RCC_PLLR_DIV_2)*/
LL_Init1msTick(40000000);
/* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */
LL_SetSystemCoreClock(40000000);
}
#ifdefUSE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
* where the assert_param error has occurred.
* @paramfile: pointer to the source file name
* @paramline: assert_param error line source number
* @retval None
*/
void assert_failed(char *file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
由上看出, st的库描述,抽象,非常到位. 整个单片机要运作, 2大基础要做好. 各个内部模块都是时钟驱动的,所有第一要务要做好时钟配置.于是就有了函数:
void SystemClock_Config(void)
这样,各个模块就可以有了生命之源,可以有条不紊的开动起来. 单片机运行,需要和外部打交道.IO口的配置就必须了. 那么再来个功能函数:
void Configure_GPIO(void);
剩下的就是用户的事情了, 一般的单片机就是个前后台系统, 一个大的while1 搞定.不断的查询,计算,读取,处理. 构成用户的APP.
纵观整个,LL库写出的IO口点灯的基本程序, 结构清晰,功能明确, 函数和变量都命名规范. 可以非常容易的上手这款最新的L496单片机.
谢谢楼主分享。 :lol 好,解决了一个入门问题,LL_mDelay 好!不仅将了过程,而且有一定的经验总结,这个很好。看资料最怕没有总结的。
页:
[1]