在线时间46 小时
UID3320130
ST金币0
蝴蝶豆0
注册时间2016-10-15
金牌会员
- 最后登录
- 2019-8-6
|
a0a.1 32b0c
期待了好久,ST昨天(2017年5月16日)终于在西安举办了第一届线下培训,这次培训的主题是“STM32低功耗设计应用Workshop”。
用ST的芯片已经有好几年的历史了,但是我之前一直用的是STM32F1和STM32F4,STM8S系列的产品,对于低功耗的产品之前还真没有怎么太多的接触,有幸能参与此次培训,感觉一整天收获颇丰,感觉花了一天时间把低功耗设计的一些大概的东西掌握了,这个学习效率还是蛮高的。所以将自己学习到的东西总结分享给大家,如果有理解不到位的地方,还望各位大神指点一二,以促进我们共同成长。
全天培训是在咖啡厅进行的,课堂上时时飘来可口的饭香味,整体氛围很好。
作为一个技术狗,我直接跳过ST关于产品线的介绍,直接杀入主题--基于STM32L476的低功耗设计,当然在这之前先介绍几个ST发布发布的非常好用的工具。
一、ST MCU Finder
这个软件我最早是在苹果软件商店发现的,下载下来觉得挺好用,所以还推荐给我群里的人了,后来又发布了安卓版本和PC桌面版(包含WINDOWS\LINUX\MAC OS)作为一个ST的忠实粉丝,我也是第一时间下载使用并推荐给群里的人。也在摩尔吧开过一次直播,和大家探讨基于ST MCU Finder 和cube MX以及keil进行产品快捷开发的课题,链接为:https://www.moore8.com/courses/1444。当然,啰嗦了这么多,还是没有给大家说说这个软件是干嘛的,我直接上图
上面的是图标,下面是软件打开后界面:
这简直就是一个选型利器啊,我们可以根据自己的需求,选择合适的检索方式,然后可以快速找到适合自己的芯片了啦。找到芯片之后还可以快速下载数据手册和其他的文档。再也不用网上到处找文档了。
二、STM32CubeMX
这又是一件利器,它可以方便的查看芯片的IO管脚图,时钟树等,不只是可以看,而且可以配合,是一款很好的IO分配,时钟树配置软件,而且它可以进行电源功耗计算。其实最厉害的应该是代码自动生成。
上面是STM32CubeMX的图标,下面是使用的详图:
以STM32L476 nucleo板子为例,创建一个项目
具体功能大家看图,下载软件使用一下就爽翻了,我就不详细描述了。
三:常用的网站及公众号:
STM32社区:https://www.stmcu.org.cn/
STM32中文官网:http://www.stmcu.com.cn
STM32四轴飞行器教程:https://www.moore8.com/courses/course/1308
公众号:STM32单片机
安利完上面两个软件,开始正式总结回忆低功耗课程的内容:
1、在低功耗案例分享中学习到的东西有以下几点:
#、影响低功耗设计的几个因素:
*芯片的工艺和制程:不同的制程芯片内部晶体管的开关功耗不同,导致整个芯片功耗不同
*晶体管数量不同:这个是显而易见的一个因素
*模拟外设的使用:模拟外设相对耗电量比较大
*RAM与Falsh大小:不同的存储容量耗电也不一样,存储功耗近似和存储空间大小成正比
*MCU供电特性:提供的电压越低,功耗也就越低,但是此时频率也越低,和电脑超频耗电量大一个道理
*时钟频率:时钟频率越高,耗电量越大
*工作模式:不同的工作模式耗电量不同,这个是显而易见的
#、功耗分为静态功耗和动态功耗,动态功耗与电压、频率、负载等关系相关
#、L4系列独有的电压转换器,可调时钟源,SMPS等.
#、外设和GPIO连接的时候,如果两端电压不一致,就会导致电流产生,从而消耗功耗,所以要仔细阅读外设手册并进行合理配置
#、IIC等外设的管脚必须外加强上拉,在进入低功耗之前把IIC的管脚设置为上拉输入模式
#、中断标识未清除也可能导致功耗上升
#、虚焊等其他情况也可能导致功耗异常
#、在数据传输未结束的时候,尽量不要切换到低功耗模式,可能会失败
#、使用低功耗串口唤醒系统的时候,如果串口波特率太高可能导致前面的数据丢失
#、一些特殊场景可以考虑把代码优先级修改为速度优先,用空间换时间
2、HandsOn环节的实验学习(具体实验安排我就不说了,请参考ppt):
代码如下:
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- #include "stm32l4xx_hal.h"
- /* USER CODE BEGIN Includes */
- #include <stdio.h>
- #include "string.h"
- #ifdef __GNUC__
- /* With GCC, small printf (option LD Linker->Libraries->Small printf
- set to 'Yes') calls __io_putchar() */
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif /* __GNUC__ */
- /* USER CODE END Includes */
- /* Private variables ---------------------------------------------------------*/
- UART_HandleTypeDef huart2;
- /* USER CODE BEGIN PV */
- /* Private variables ---------------------------------------------------------*/
- __IO uint8_t ReceiveStatus = 0;
- __IO uint16_t RxCmdCounter = 0;
- __IO uint8_t ReadyToReception = 0;
- __IO uint8_t CmdEnteredOk = 0;
- #define LR_ASCII_VALUE ((uint8_t)0x0A)
- #define CR_ASCII_VALUE ((uint8_t)0x0D)
- #define RXCOMMANDSIZE 0x20
- #define RXBUFFERSIZE 0x01
- char RxCommand[RXCOMMANDSIZE];
- uint8_t RxBuffer[RXBUFFERSIZE] = {0}; //transmitting byte per byte
- char temp; //initialisation character
- char * s;
- /* USER CODE END PV */
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- void Error_Handler(void);
- static void MX_GPIO_Init(void);
- static void MX_USART2_UART_Init(void);
- /* USER CODE BEGIN PFP */
- /* Private function prototypes -----------------------------------------------*/
- void DecodeReception(void);
- void LSE_OFF_Config(void);
- extern void test_shutdown(void);
- extern void test_standby(void);
- extern void test_lpsleep_2mhz(void);
- extern void test_stop2(void);
- /* USER CODE END PFP */
- /* USER CODE BEGIN 0 */
- /* USER CODE END 0 */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* USER CODE END 1 */
- /* MCU Configuration----------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* Configure the system clock */
- SystemClock_Config();
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_USART2_UART_Init();
- /* USER CODE BEGIN 2 */
- HAL_Delay(1000);//delay 1s
- /* Output a message on Hyperterminal using printf function */
- printf("\n\rREADY\n\r");
- printf("Please enter the test number according below options\n\r");
- printf(" 0 (SHUTDOWN) \n\r");
- printf(" 1 (STANDBY) \n\r");
- printf(" 2 (STOP2) \n\r");
- printf(" 3 (LPSLEEP 2MHz - FLASH OFF) \n\r");
-
- printf(" --> \n\r");
-
- while (CmdEnteredOk != 0x1) {
- ReceiveStatus = 0;
- while (ReceiveStatus != 0x1){
- /* Start the USART2 Receive process to receive the RxBuffer */
- if(HAL_UART_Receive_IT(&huart2, RxBuffer, RXBUFFERSIZE) != HAL_OK)
- {
- Error_Handler();
- }
- while (!ReadyToReception);
- ReadyToReception = 0;
- DecodeReception();
- }
- CmdEnteredOk = 1;
- s = RxCommand;
-
- // __EFF_NENW1NW2 __ATTRIBUTES int strcmp(const char *, const char *);
- // strcmp(s, "x\r") ==0, input char is x\r, it is true
-
- // TODO 5: If receive char "0", enter into Shutdown mode
-
-
- // TODO 6: If receive char "1", enter into Standby mode
-
-
- // TODO 7: If receive char "2", enter into Stop2 mode
-
-
- // TODO 8: If receive char "3", enter into Low Power Sleep
-
-
- else {
- printf("Invalid test number.. Please enter again\n\r");
- CmdEnteredOk = 0;
- /* Reset received test number array */
- memset(RxCommand, 0, RXCOMMANDSIZE);
- }
-
- }
-
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
- /** System Clock Configuration
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- RCC_PeriphCLKInitTypeDef PeriphClkInit;
- /**Initializes the CPU, AHB and APB busses clocks
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
- RCC_OscInitStruct.MSIState = RCC_MSI_ON;
- RCC_OscInitStruct.MSICalibrationValue = 0;
- RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /**Initializes the CPU, AHB and APB busses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
- {
- Error_Handler();
- }
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
- PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
- {
- Error_Handler();
- }
- /**Configure the main internal regulator output voltage
- */
- if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
- {
- Error_Handler();
- }
- /**Configure the Systick interrupt time
- */
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
- /**Configure the Systick
- */
- HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
- /* SysTick_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
- }
- /* USART2 init function */
- static void MX_USART2_UART_Init(void)
- {
- huart2.Instance = USART2;
- huart2.Init.BaudRate = 9600;
- huart2.Init.WordLength = UART_WORDLENGTH_8B;
- huart2.Init.StopBits = UART_STOPBITS_1;
- huart2.Init.Parity = UART_PARITY_NONE;
- huart2.Init.Mode = UART_MODE_TX_RX;
- huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart2.Init.OverSampling = UART_OVERSAMPLING_16;
- huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart2) != HAL_OK)
- {
- Error_Handler();
- }
- }
- /** Configure pins as
- * Analog
- * Input
- * Output
- * EVENT_OUT
- * EXTI
- */
- static void MX_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOC_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /*Configure GPIO pin : PC13 */
- GPIO_InitStruct.Pin = GPIO_PIN_13;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
- }
- /* USER CODE BEGIN 4 */
- PUTCHAR_PROTOTYPE
- {
- /* Place your implementation of fputc here */
- /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
- HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
- void DecodeReception(void)
- {
- /* Read one byte from the receive data register */
- temp = (char) RxBuffer[0];
- RxCommand[RxCmdCounter++] = temp;
- /* Check if is an LR/CR character */
- if ((temp == CR_ASCII_VALUE) || (temp == LR_ASCII_VALUE))
- {
- /* echo entered command on terminal */
- printf("You entered below test number:\n\r");
- printf(RxCommand);
- printf("\n\r");
- RxCmdCounter = 0;
-
- ReceiveStatus = 1;
- }
- }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- ReadyToReception = 1;
- }
- void SystemClock_2MHz(void)
- {
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- /* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
- RCC_OscInitStruct.MSIState = RCC_MSI_ON;
- RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
- RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
- if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- /* Initialization Error */
- Error_Handler();
- }
-
- /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
- clocks dividers */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
- {
- /* Initialization Error */
- Error_Handler();
- }
-
- }
- void GPIO_AnalogState_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /* Set all GPIO in analog state to reduce power consumption, */
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- __HAL_RCC_GPIOC_CLK_ENABLE();
- __HAL_RCC_GPIOD_CLK_ENABLE();
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOG_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Pin = GPIO_PIN_All;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
- __HAL_RCC_GPIOA_CLK_DISABLE();
- __HAL_RCC_GPIOB_CLK_DISABLE();
- __HAL_RCC_GPIOC_CLK_DISABLE();
- __HAL_RCC_GPIOD_CLK_DISABLE();
- __HAL_RCC_GPIOE_CLK_DISABLE();
- __HAL_RCC_GPIOF_CLK_DISABLE();
- __HAL_RCC_GPIOG_CLK_DISABLE();
- __HAL_RCC_GPIOH_CLK_DISABLE();
- }
- void LSE_OFF_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- /* set LSE OFF */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
- RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
- if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- /* Initialization Error */
- Error_Handler();
- }
- }
- // TODO 1: Enter into Shutdown mode
- // TODO 2: Enter into Standby mode
- // TODO 3: Enter into Stop2 mode
- // TODO 4: Enter into Low Power Sleep mode
- /* USER CODE END 4 */
- /**
- * @brief This function is executed in case of error occurrence.
- * @param None
- * @retval None
- */
- void Error_Handler(void)
- {
- /* USER CODE BEGIN Error_Handler */
- /* User can add his own implementation to report the HAL error return state */
- while(1)
- {
- }
- /* USER CODE END Error_Handler */
- }
- #ifdef USE_FULL_ASSERT
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- void assert_failed(uint8_t* file, uint32_t line)
- {
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* USER CODE END 6 */
- }
- #endif
- /**
- * @}
- */
- /**
- * @}
- */
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码 上面是修改之前的代码。
我自己测试的结果是(图上红色的数字是我的测试结果,与理论值基本吻合):
大家也可以根据帖子里共享的ppt思考一下补全代码。
总之昨天学到了以下东西:
1、知道了设计低功耗产品时,硬件层面和软件层面各应该注意什么
2、能够使用CUBE MX配置工程并生成项目代码
3、计算理论功耗,测量实际功耗并对比
收获满满的一天,下面把学习的资料分享给大家:
00_Part0_20170516_Xi'an_MassMarket_Begin.pdf
(1.22 MB, 下载次数: 187)
|
评分
-
查看全部评分
|