谷动谷力

 找回密码
 立即注册
查看: 1151|回复: 0
打印 上一主题 下一主题
收起左侧

STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试

[复制链接]
跳转到指定楼层
楼主
发表于 2023-7-19 08:37:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sunsili 于 2023-7-19 08:39 编辑

STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试
来源:EEWORLD论坛网友 bigbat 版权归原作者所有

开箱硬件测评分析随着物联网的不断推进,网络通讯安全级别也在不断提高,普通的MCU在应对加解密和安全验证等应用时就有点力不从心,MCU的主要应用是小型的嵌入式设备,但安全应用又需要硬件具备一定性能,安全算法除了占用一定的MCU性能外还需要大量的代码和RAM空间,因而市场出现了很多“组合设计”,最常见的就是“MCU+高性能通讯模块”,在应用环境恶劣的场景下面临挑战,如在北方冬季无人值守的站点,因气温很低,会给通讯模块带来很多问题。基于arm Cortex-M33内核的高性能MCU — STM32H5,针对安全性和通讯性能增加了很多的性能。STM32H5系列提供了较大RAM(640K)和Flash(2M+),提供 4K Backup RAM 用来存储待机数据,主频更是提高到了250MHz。在安全方面,STM32H5 也是提供了M33内核的全部安全特性,TrustZone、内存保护、加密存储等特性。
NUCLEO-H563ZI 是主核为STM32H563ZI、144PIN脚的DEMO板。该板接口由原来的USB接口更新为 Type-C 接口,有以下外设:1、一个 RJ45 以太网口、PHY 使用的是 LAN8742,一个网络变压器;2、一个 VDD 触发按键作为输入,按键接了一个ESD ALC6V1的保护;3、一个LPUSART 接口,链接到板载的虚拟串口,与ST-LINK V3共用一个USB;4、一个全速 USB TYPE-C 接口,提供芯片的USB功能,及硬件保护和电源管理;5、LED和REST按键等外设。从板卡设计中可以看出ST公司加入了大量的接口保护设计参考。因板卡新的硬件特性,需要升级软件环境,STM32CubeMX需要升级到 v6.9 版,Java jre升级到17版;Keil 升级到 v6.0以上版本,同时下载STM32H5的包,ST-link V3的驱动也需要升级。点灯程序: NYUCLEO-H563ZI开发板的硬件引脚基本已经配置好了,只需配置没有扩展的引脚。程序点亮的是LED2。程序不是很复杂,代码很简单,但是M33内核需要的设置却很多。
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}

GPIO和PWM测试为了呈现 STM32H563ZI 接近MPU的性能,本次测试使用freeRTOS系统进行PWM和GPIO的测试。首先,需要安装STM32Cube的STM32H5的freeRTOS系统模块,新建项目时选择“ACCESS TO EXAMPLE SELECTOR”项目,选择开发板NUCLEO-H563ZI,选择FreeRTOS_Semaphore_LowPower项目。项目默认打开了PWR管理,还有三个LED外设。我们的评测是使用一个低功耗定时器 LPTIM4 作为信号源来控制 GPIO 的输出。
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : app_freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os2.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DEFAULT_TIMEOUT (1000)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
extern LPTIM_HandleTypeDef hlptim4;
/* USER CODE END Variables */
/* Definitions for MainThread */
osThreadId_t MainThreadHandle;
const osThreadAttr_t MainThread_attributes = {
  .name = "MainThread",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 256 * 4
};
/* Definitions for BinarySemaphore */
osSemaphoreId_t BinarySemaphoreHandle;
const osSemaphoreAttr_t BinarySemaphore_attributes = {
  .name = "BinarySemaphore"
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void SystemClock_Config(void);
/* USER CODE END FunctionPrototypes */
void MainThread_Entry(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* USER CODE BEGIN PREPOSTSLEEP */
void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
  /* This is needed to prevent TIM6 from triggering an interrupt,
   * which could prevent the CPU from entering STOP mode */
  HAL_SuspendTick();
  /* Start low power timer */
  HAL_LPTIM_TimeOut_Start_IT(&hlptim4, DEFAULT_TIMEOUT);
  /* Enter STOP mode */
  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
  /* Restore Clock settings */
  SystemClock_Config();
  /* Resume HAL timebase */
  HAL_ResumeTick();
}
/* USER CODE END PREPOSTSLEEP */
/**
  * @brief FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */
  /* creation of BinarySemaphore */
  BinarySemaphoreHandle = osSemaphoreNew(1, 1, &BinarySemaphore_attributes);
  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */
  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */
  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */
  /* creation of MainThread */
  MainThreadHandle = osThreadNew(MainThread_Entry, NULL, &MainThread_attributes);
  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */
  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_MainThread_Entry */
/**
* @brief Function implementing the MainThread thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_MainThread_Entry */
void MainThread_Entry(void *argument)
{
  /* USER CODE BEGIN MainThread */
  /* Infinite loop */
  for(;;osSemaphoreAcquire(BinarySemaphoreHandle, osWaitForever))
  {
    HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin);
  }
  /* USER CODE END MainThread */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
  if(hlptim->Instance == LPTIM4)
  {
    osSemaphoreRelease(BinarySemaphoreHandle);
    HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);
  }
}
/* USER CODE END Application */

程序中首先声明了一个信号量 BinarySemaphoreHandle,作为 GPIO 的控制开关,然后在中断回调 HAL_LPTIM_CompareMatchCallback 中生成这个信号量。
//信号量
osSemaphoreId_t BinarySemaphoreHandle;
//回调函数/* Private application code --------------------------------------------------*//* USER CODE BEGIN Application */void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
  if(hlptim->Instance == LPTIM4)
  {
    osSemaphoreRelease(BinarySemaphoreHandle);
    HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);
  }
}

信号生成后,等待系统自己调度,这时需要将LPTIM4中断关掉。HAL_LPTIM_TimeOut_Stop_IT(&hlptim4);
/* USER CODE END Header_MainThread_Entry */void MainThread_Entry(void *argument)
{
  /* USER CODE BEGIN MainThread */
  /* Infinite loop */
  for(;;osSemaphoreAcquire(BinarySemaphoreHandle, osWaitForever))
  {
    HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);
  }
  /* USER CODE END MainThread */
}

信号到达后翻转GPIO输出,系统运行后LED2,进入不停的闪烁。这里我把LED1改成了LED2,PWM的测试选择了 FreeRTOS_Mutex 例程,主要是因为 PWM 的输出需要更加严格的同步和控制。低功耗模式不适合该应用。PWM的输出设置需要理清程序的同步逻辑。程序首先定义了两个线程Thread1和Thread2,一个Mutex锁信号MutexHandle,通过这个信号进行 UART 资源的保护运行。
osThreadId_t Thread1Handle;
const osThreadAttr_t Thread1_attributes = {
  .name = "Thread1",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 256 * 4
};
/* Definitions for Thread2 */
osThreadId_t Thread2Handle;
const osThreadAttr_t Thread2_attributes = {
  .name = "Thread2",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 256 * 4
};
/* Definitions for Mutex */
osMutexId_t MutexHandle;
const osMutexAttr_t Mutex_attributes = {
  .name = "Mutex"
};

首先两个线程在运行前半段使用信号锁进行共用资源 uart 的运行,后面进行运行。
/* USER CODE BEGIN Header_Thread1_Entry */
/**
* @brief Function implementing the Thread1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Thread1_Entry */
void Thread1_Entry(void *argument)
{
  /* USER CODE BEGIN Thread1 */
  uint16_t i;
  /* Infinite loop */
  for(i = 0; i < 10; ++i)
  {
  #if EXAMPLE_USES_MUTEX
  osMutexAcquire(MutexHandle, osWaitForever);
  printf ("Thread1: Mutex Acquired!\n");
  #endif

  printf("Thread1 : This is message number %u\n", i+1);

#if EXAMPLE_USES_MUTEX
  printf ("Thread1: Mutex Released!\n");
  osMutexRelease(MutexHandle);
  #endif
    HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin);
    osDelay(200);
  }

  while(1)
  {
    HAL_GPIO_TogglePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin);
    osDelay(1000);
  }
  /* USER CODE END Thread1 */
}

/* USER CODE BEGIN Header_Thread2_Entry */
/**
* @brief Function implementing the Thread2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Thread2_Entry */
void Thread2_Entry(void *argument)
{
  /* USER CODE BEGIN Thread2 */
  uint16_t i;

  /* Infinite loop */
  for(i = 0; i < 10; ++i)
  {
  #if EXAMPLE_USES_MUTEX
    osMutexAcquire(MutexHandle, osWaitForever);
    printf ("Thread2: Mutex Acquired!\n");
    #endif

    printf("Thread2 : This is message number %u\n", i+1);
#if EXAMPLE_USES_MUTEX
    printf ("Thread2: Mutex Released!\n");
    osMutexRelease(MutexHandle);
    #endif
    HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);
    osDelay(200);
  }

  while(1)
  {
    HAL_GPIO_TogglePin(LED2_YELLOW_GPIO_Port, LED2_YELLOW_Pin);
    osDelay(1000);
  }
    /* USER CODE END Thread2 */
}

/* Private application code --------------------------------------------------*//* USER CODE BEGIN Application */
/* USER CODE END Application */

进程先获取信号锁,在进行打印输出,输出完成后再解锁,这样可以保证三段打印都是同一个线程的输出。可以看出每次的输出都是一个线程的信息。下面进行PWM的改造测试PWM的设置如图,使用LED1作为PWM的输出,所以设置PB0作为TIM3的CH3通道,PWM输出,脉宽比为50%,所以计数为2048,PLUSE VALUE=1024。设置好以后将程序进行改造,另起一个项目通过CUBE生成初始化代码,然后改造项目。
/* USER CODE BEGIN Header_Thread1_Entry */
/**
* @brief Function implementing the Thread1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Thread1_Entry */
void Thread1_Entry(void *argument)
{

  osMutexAcquire(MutexHandle, osWaitForever);
  printf ("Thread1: Mutex Acquired!\n");
  printf("Thread1 : PWM starter\n ");
  printf ("Thread1: Mutex Released!\n");
  osMutexRelease(MutexHandle);
   HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
  while(1)
  {
    osDelay(1);
  }
  /* USER CODE END Thread1 */
}

项目启动后。可以看到LED1开始开始工作。
+10
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-12-27 20:02 , Processed in 0.106524 second(s), 42 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表