谷动谷力
标题: STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试 [打印本页]
作者: sunsili 时间: 2023-7-19 08:37
标题: STM32H5测评 | 开箱硬件测评分析与GPIO和PWM测试
本帖最后由 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开始开始工作。
欢迎光临 谷动谷力 (http://bbs.sunsili.com/) |
Powered by Discuz! X3.2 |