这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【STM32H747I-DISCO试用】4、配置OpenAMP实现温度传递

共1条 1/1 1 跳转至

【STM32H747I-DISCO试用】4、配置OpenAMP实现温度传递

高工
2025-11-15 21:47:40     打赏

【前言】

STM32H7双核MCU,双核的通信有好几种方式,此次采用OpenAMP来实现。

【STM32CubeMX图形化配置】

1、要配置OpenAPM,必须先使能HSEM的全局中断,才能使用能OpenAMP

image.png2、接下来使能OPENAMP_M4与OPENAMP_M7,使用默认配置即可。

image.png

3、MPU设置

我们要实现OpenAMP交换数据,需要选择M7与M4可以共同访问的内存空间,根据数据手册SRAM4是可以共同访问的内存。

image.png

在M7内存中,我们需要配置SRAM4的MPU。

image.png

使用后需要重新生成代码。

【代码编写】

一、STM32H747_M7 在main.c中添加

1、添加变量以及函数声明

/* USER CODE BEGIN PTD */
#define RPMSG_CHAN_NAME              "openamp_AHT20"
/* USER CODE END PTD */
/* USER CODE BEGIN PM */
static volatile int message_received;
static volatile int service_created;
volatile unsigned int received_data_str;
static struct rpmsg_endpoint rp_endpoint;

static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv);
void service_destroy_cb(struct rpmsg_endpoint *ept);
void new_service_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest);

/* USER CODE END PM */

2、实现回调函数

/* USER CODE BEGIN 4 */
AHT20_DataTypedef recv_aht_data = {0.0f, 0.0f};
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
                size_t len, uint32_t src, void *priv)
{
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_RESET);
	if (len == sizeof(AHT20_DataTypedef)) {
	        // 将接收的数据拷贝到结构体(直接强转+赋值,或用 memcpy)
	        recv_aht_data = *(AHT20_DataTypedef *)data;
	        // 或用 memcpy(效果一致,更安全):
	        // memcpy(&recv_aht_data, data, sizeof(recv_aht_data));

	        message_received = 1; // 标记接收成功
	        // 可选:打印解析后的数据
	        // printf("Recv AHT20: Hum=%.2f %%RH, Temp=%.2f °C\r\n",
	        //        recv_aht_data.humidity, recv_aht_data.temperature);
	    } else {
	        // 数据长度不匹配,标记失败
	        message_received = 0;
	        // printf("Recv Err: Len=%d (Need %d)\r\n", len, sizeof(AHT20_DataTypedef));
	    }

	    return 0;
}


void service_destroy_cb(struct rpmsg_endpoint *ept)
{
  /* this function is called while remote endpoint as been destroyed, the
   * service is no more available
   */
  service_created = 0;
}

void new_service_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest)
{
  /* create a endpoint for rmpsg communication */
	OPENAMP_create_endpoint(&rp_endpoint, name, dest, rpmsg_recv_callback,
	                          service_destroy_cb);
	service_created = 1;
}
/* USER CODE END 4 */

3、创建一个任务:

/* USER CODE END Header_openAMP_task */

void openAMP_task(void *argument)
{
  /* USER CODE BEGIN openAMP_task */
  /* Infinite loop */
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_SET);
	  MAILBOX_Init();
	    /* Initialize the rpmsg endpoint to set default addresses to RPMSG_ADDR_ANY */
	  rpmsg_init_ept(&rp_endpoint, RPMSG_CHAN_NAME, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
	                 NULL, NULL);
	  /* Initialize OpenAmp and libmetal libraries */
	  if (MX_OPENAMP_Init(RPMSG_MASTER, new_service_cb)!= HAL_OK)
	    Error_Handler();
	  OPENAMP_Wait_EndPointready(&rp_endpoint);
	  for(;;)
	  {
		  while(service_created)
			{
				OPENAMP_check_for_message();
				osDelay(1);
			}
	    osDelay(1);
	  }
  /* USER CODE END openAMP_task */
}

4、修改STM32H747XIHX_FLASH.ld 

/* Specify the memory areas */
MEMORY
{
FLASH (rx)     : ORIGIN = 0x08100000, LENGTH = 1024K
RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
OPENAMP_RSC_TAB (xrw)     : ORIGIN = 0x38000000, LENGTH = 1K
OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K
}
__OPENAMP_region_start__  = ORIGIN(OPEN_AMP_SHMEM);
__OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM);

在最后面添加:

.openamp_section (NOLOAD) : {
. = ABSOLUTE(0x38000000);
*(.resource_table)
} >OPENAMP_RSC_TAB  AT > FLASH
.ARM.attributes 0 : { *(.ARM.attributes) }
}

二、STM32H747_M4内核代码添加

修改app.c代码如下:

/*
 * app.c
 *
 *  Created on: Nov 15, 2025
 *      Author: liujianhua
 */

#include "app.h"
#include "stdio.h"
#include "AHT20.h"

#include "openamp.h"

#define RPMSG_CHAN_NAME              "openamp_AHT20"


static volatile int message_received;
static volatile int service_created;
volatile unsigned int received_data_str;
static struct rpmsg_endpoint rp_endpoint;

static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv);
void service_destroy_cb(struct rpmsg_endpoint *ept);
void new_service_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest);

static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
               size_t len, uint32_t src, void *priv)
{
//	uint8_t cmd = *(uint8_t *)data;
	message_received = *((unsigned int *) data);
	printf("openamp recv data:%d",message_received);
    return 0;
}

void Run(void)
{
	float humidity = 0.0f, temperature = 0.0f;
	AHT20_DataTypedef aht_data; // 定义结构体实例
	AHT20_StatusTypeDef aht_status;
	int status = 0;
	MAILBOX_Init();
	if(MX_OPENAMP_Init(RPMSG_REMOTE,NULL) != HAL_OK)
	{
		Error_Handler();
	}
	status = OPENAMP_create_endpoint(&rp_endpoint,
									RPMSG_CHAN_NAME,
									RPMSG_ADDR_ANY,
									rpmsg_recv_callback,NULL);
	if(status < 0)
	{
		Error_Handler();
	}

	  // 1. 初始化AHT20
	  aht_status = AHT20_Init();
	  if (aht_status == AHT20_OK) {
		  printf("AHT20 Init Success!\r\n");
	  } else {
		  printf("AHT20 Init Fail! Code: %d\r\n", aht_status);
		  while (1); // 初始化失败,死循环
	  }
	  while(1)
	  {
		  aht_status = AHT20_ReadData(&humidity, &temperature);
		  if (aht_status == AHT20_OK) {
			  // 打印温湿度(保留2位小数)
			  printf("Humidity: %.2f %%RH | Temperature: %.2f\r\n",\
					  humidity, temperature);
		  } else {
			  // 打印错误信息
			  printf("Read Fail! Code: %d\r\n", aht_status);
		  }
		  // 2. 将温湿度赋值给结构体
		  aht_data.humidity = humidity;
		  aht_data.temperature = temperature;
		  int ret = rpmsg_send(&rp_endpoint, &aht_data, sizeof(aht_data));
		  if (ret < 0) {
			   printf("OpenAMP Send Fail! Ret: %d\r\n", ret);
		  } else {
				  printf("Send Success: Hum=%.2f, Temp=%.2f\r\n", aht_data.humidity, aht_data.temperature);
			  }
		  HAL_Delay(1000); // 1秒读取一次

	  }

}

2、修改STM32H747XIHX_FLASH.ld

/* Specify the memory areas */
MEMORY
{
FLASH (rx)     : ORIGIN = 0x08100000, LENGTH = 1024K
RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
OPENAMP_RSC_TAB (xrw)     : ORIGIN = 0x38000000, LENGTH = 1K
OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K
}
__OPENAMP_region_start__  = ORIGIN(OPEN_AMP_SHMEM);
__OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM);

最文档最后面添加:

.openamp_section (NOLOAD) : {
. = ABSOLUTE(0x38000000);
*(.resource_table)
} >OPENAMP_RSC_TAB  AT > FLASH
.ARM.attributes 0 : { *(.ARM.attributes) }
}

【验证】

两个内核编译下载后,我们观察串口助手的打印日志

image.png

观察屏TouchGFX效果如下:

image.png

用手按下AHT20,观察温度变化:

image.png

可以看到动态的更了GUI显示。

【总结】

STM32H747的双核,M7内核主核高,GUI显示效果好,M4内核可以处理数据收发等,通过OpenAMP将数据同步给M7做显示,这样就各司其责。

【视频】






关键词: STM32H747I-DISCO     AHT20     传感    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]