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

【经验分享】STM32L0系列之【工程开始】

[复制链接]
STMCU小助手 发布时间:2021-11-15 21:01
1.前言
一直没有正经从完全无知开始去接触了解一款新的stm型号芯片。趁着这次11月份的新项目的开端需要用到stm32L0系列的单片机,搭载lora模块进行项目开发。这里开个系列博客记录下学习过程和调试过程。

2.开发工具
以前做stm32的开发都是基本用的stm32F系列,代码结构也是套用的公司以前的模板。
本次L0系列采用了st公司提供的一个新的(对笔者来说是新的,之前没用过,其实以前出来比较久了)开发代码生成工具-STMCubeMx。

20191125101556652.png


这个就是安装完后的工具图标。具体安装下载过程这里不做赘述,不了解的朋友可自行百度。

3.简述开发工具生成的代码结构

Stm32CubeMx自动用户所选的IC型号以及需要用到的mcu资源,外设等自动生成相应的代码,生成的代码使用HAL库。其代码结构基本不需要进行什么修改(用户所选所设置皆正确的情况下),仅仅需要对一些HAL中的回调进行重写(如果你需要)。
20191125102002856.png


如图,代码编译工具还是使用keil软件,根据图中代码结构可以很清晰的看到整个代码分为
Application和Drivers(附加CMSIS)
Application里分为MDK-ARM和User。
MDK-ARM是代码工程的一个目录(基于编译,比如编译生成文件,中间文件.o之类的)
User是用户程序的主入口,如main.c等。
需要注意的是User中还包含除main.c之外的两个文件,其中一个msp文件是工具自动生成的,后面分析。ic文件则是和中断回调相关的,这个相比都比较清楚。

20191125102405305.png


在Drivers中包含HAL_Driver和CMSIS.
CMSIS则是和内核相关的,如M0,M3等之类的内核。
HAL_Driver则是st给用户提供一些接口,如flash,rtc等的操作接口。

3.1 main.c简析
最简单main.c里面的代码至少包括三部分:HAL_Init,SystemClock_Config,while(1);

  1. int main(void)
  2. {
  3.         HAL_Init(); //HAL库的初始化
  4.         SystemClock_Config();//系统时钟配置初始化
  5.         while(1)//主程序的运行
  6.         {
  7.         }
  8. }
复制代码

3.2 代码运行流程以及HAL库的调用结构
3.2.1 HAL_Init()
  1. /**
  2.   * @brief This function configures the Flash prefetch, Flash preread and Buffer cache,
  3.   *        Configures time base source, NVIC and Low level hardware
  4.   * @note This function is called at the beginning of program after reset and before
  5.   *       the clock configuration
  6.   * @note The time base configuration is based on MSI clock when exiting from Reset.
  7.   *       Once done, time base tick start incrementing.
  8.   *        In the default implementation,Systick is used as source of time base.
  9.   *        the tick variable is incremented each 1ms in its ISR.
  10.   * @retval HAL status
  11.   */
  12. HAL_StatusTypeDef HAL_Init(void)
  13. {
  14.   HAL_StatusTypeDef  status = HAL_OK;

  15.   /* Configure Buffer cache, Flash prefetch,  Flash preread */
  16. #if (BUFFER_CACHE_DISABLE != 0)
  17.   __HAL_FLASH_BUFFER_CACHE_DISABLE();
  18. #endif /* BUFFER_CACHE_DISABLE */

  19. #if (PREREAD_ENABLE != 0)
  20.   __HAL_FLASH_PREREAD_BUFFER_ENABLE();
  21. #endif /* PREREAD_ENABLE */

  22. #if (PREFETCH_ENABLE != 0)
  23.   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  24. #endif /* PREFETCH_ENABLE */

  25.   /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
  26.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
  27.   {
  28.     status = HAL_ERROR;
  29.   }
  30.   else
  31.   {
  32.     /* Init the low level hardware */
  33.     HAL_MspInit();
  34.   }

  35.   /* Return function status */
  36.   return status;
  37. }
复制代码

这里抽出2个关键函数:
HAL_InitTick,HAL_MspInit
可以看到mcu一启动则调用HAL_InitTick,它的功能是使用SysTick作为时基源并配置1ms刻度(复位后的默认时钟为MSI)
如果该函数出错,则调用HAL_MspInit。
这里提下该函数HAL_MspInit是被__weak修饰,叫做弱函数。被这种修饰的函数,通常需要用户自己去实现。实现的位置在哪里?还记得前面提到msp文件吗,就在那里面,当然你也可以写到你想写的地方,msp这个文件只是为了方面管理整个代码工程中的需要重写的函数。

3.2.2 SystemClock_Config()
  1. /**
  2.   * @brief System Clock Configuration
  3.   * @retval None
  4.   */
  5. void SystemClock_Config(void)
  6. {
  7.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  8.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  9.   /** Configure the main internal regulator output voltage
  10.   */
  11.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  12.   /** Initializes the CPU, AHB and APB busses clocks
  13.   */
  14.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  15.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  16.   RCC_OscInitStruct.MSICalibrationValue = 0;
  17.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  18.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  19.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  20.   {
  21.     Error_Handler();
  22.   }
  23.   /** Initializes the CPU, AHB and APB busses clocks
  24.   */
  25.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  26.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  27.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  28.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  29.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  30.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  31.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  32.   {
  33.     Error_Handler();
  34.   }
  35. }
复制代码

这里可以看到对于mcu的时钟选择配置,完全对上刚开始创建工程时的选择。先简单将这个函数分隔下:
第一步:配置内部主稳压器的输出电压
第二步:初始化RCC振荡器。HAL_RCC_OscConfig,这里选择了MSI时钟,频率是4.194Mhz
第三步:初始化CPU,AHB和APB总线时钟,HAL_RCC_ClockConfig
如图;

20191125103747351.png


ps:关于STM32l0的时钟相关,可以参考datasheet。也可以往官网下载(英文版)

4. 话说在前面系列
在使用St’m32CubeMx生成代码的时候,后期单独修改代码的时候,需要注意:
1.stm32l0xx_hal_conf.h 头文件指定了哪些文件是否参与编译,文件内是按模块声明的。
2.第一次调试测试单独功能的时候,可以使用工具生成单独模块的代码进行单独测试。



收藏 评论0 发布时间:2021-11-15 21:01

举报

0个回答

所属标签

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