3配置项目
在Project Manager主选项卡下,将Project选项卡下的最小堆栈大小配置为 0xC00 。这是第一个值,以后可以根据应用需要进行调整。
在Advanced Settings选项卡下,将 LPUART 驱动程序更改为 LL 以节省一点内存堆大小。由于我们不需要 ADC 和 I2C 初始化函数(由 BSP 驱动程序处理),因此取消选中MX_I2C2_Init 和 MX_ADC1_Init 函数的 生成代码 。
4将BSP添加到项目中
需要将 X-NUCLEO-SRC1M1 扩展板的5 分钟板级支持包 (BSP) 添加到项目中。这些文件需要手动复制到项目的文件夹中。从 GitHub x-cube-tcpp
获取最新的 BSP 。
手动复制以下三个文件夹:
进入:
然后,在项目的根文件夹中创建一个名为“ .extSettings ”的文件(请注意文件名中的点字符)并用以下代码填充它:
该文件用于告诉代码生成器在生成项目时包含 BSP 文件。
5生成代码
使用 Ctrl+s 保存文件,并在出现提示时选择生成代码。您还可以通过单击项目/生成代码或按 Alt+K 从 STM32CubeIDE 菜单生成代码。
出现一条警告,通知未定义正确的 HAL 时基。使用专用定时器作为 HAL 时基源更安全。
对于此演示,可以通过单击是忽略以下警告。
信息 |
---|
这成为在即将发布的固件包交付中推荐的标准工作方式,尤其是在使用 CMSIS OS V2 时,它将 Systick 定义为 FreeRTOS™ 时基。对于此演示,可以通过单击是忽略警告。 |
在这个项目中,可以找到不同的文件夹:
- USBPD文件夹包含我们需要编辑以丰富 Power Delivery 应用程序的源文件。
- Core文件夹包含项目核心的源文件。
- Drivers文件夹包含 STM32的HAL 驱动程序,以及 Nucleo 板和 X-NUCLEO-SRC1M1 扩展板的 BSP。
- Middleware文件夹包含 FreeRTOS™ 和 USB-PD的源文件和库。
- Utilities文件夹包含 GUI(UCPD 监视器)和跟踪器嵌入式源文件部分。
项目的 Explorer 视图中的Drivers文件夹必须包含之前添加的 BSP 文件夹。
6完整的USB-PD应用
Now that the peripherals are initialized by STM32CubeMX, some minimum level of the application needs to be added:
- src1m1_conf.h file needs to be created from its template, and added to the project
- User code needs to be added in several files
6.1 Add SRC1M1 configuration file
In the Drivers\\BSP\\X-NUCLEO-SRC1M1 folder you will find src1m1_conf_template.h . Copy it to Core\\Inc folder, and rename it src1m1_conf.h . It is the configuration file used for the X-NUCLEO-SRC1M1 BSP.
6.2 Modification in stm32g0xx_it.c
|
在/ USER CODE BEGIN-END Includes / 标签之间添加以下代码:
/* 用户代码开始包括 */
#include "src1m1_conf.h"
/* 用户代码结束包括 */
在/ USER CODE BEGIN-END 1 / 标签之间添加以下代码:
/* USER CODE BEGIN 1 */
#if defined(TCPP0203_SUPPORT)
/**
* @brief 该函数处理外线 4_15 中断请求。
*(在 TCPP0203 管理的情况下关联到 FLGn 线)
* @retval None
*/
void TCPP0203_PORT0_FLG_EXTI_IRQHANDLER ( void )
{
/* 管理标志 */
if ( TCPP0203_PORT0_FLG_EXTI_IS_ACTIVE_FLAG () != RESET )
{
/* 调用 BSP USBPD PWR 回调 */
BSP_USBPD_CPWR_CWR_R ( USBPD_PWR_TYPE_C_PORT_1 );
/* 清除标志 */
TCPP0203_PORT0_FLG_EXTI_CLEAR_FLAG ();
}
}
#endif /* TCPP0203_SUPPORT */
/* 用户代码结束 1 */
6.3 usbpd_dpm_user.h中的修改
在/ USER CODE BEGIN-END Typedef / 标签之间添加以下代码:
/* 用户代码开始 Typedef */
typedef struct
{
uint32_t DPM_ListOfRcvSNKPDO [ USBPD_MAX_NB_PDO ]; /*!< 从端口伙伴接收到的接收器功率数据对象列表
(当端口伙伴是接收器或 DRP 端口时)。*/
uint32_t DPM_NumberOfRcvSNKPDO ; /*!< 从端口伙伴接收到的接收器功率数据对象的数量
(当端口伙伴是接收器或 DRP 端口时)。
此参数必须设置为低于
USBPD_MAX_NB_PDO */
uint32_t DPM_RDOPosition ; /*!< 请求的 DO 在功能源列表中的 RDO 位置 */
uint32_t DPM_RDOPositionPrevious ; /*!< RDO 所请求 DO 在功能源列表中的位置 */
uint32_t DPM_RequestedVoltage ; /*!< 请求电压值 */
uint32_t DPM_RequestedCurrent ; /*!< 请求电流值 */
uint32_t DPM_RcvRequestDOMsg ;
uint32_t DPM_RequestDOMsg ; /*!< 要发送的请求功率数据对象消息 */
uint32_t DPM_RequestDOMsgPrevious ; /*!< 要发送的上一个请求电源数据对象消息 */
} USBPD_HandleTypeDef ;
/* 用户代码结束类型定义 */
在/ USER CODE BEGIN-END Private_Variables / 标签之间添加以下代码:
/* 用户代码开始 Private_Variables */
extern USBPD_HandleTypeDef DPM_Ports [ USBPD_PORT_COUNT ];
/* 用户代码结束 Private_Variables */
6.4 usbpd_pdo_defs.h中的修改
在/ USER CODE BEGIN-END typedef / 标签之间添加以下代码:
/* 用户代码开始 typedef */
/**
* @brief USBPD 端口 PDO 结构定义
*/
typedef struct
{
uint32_t * ListOfPDO ; /*!< Power 数据对象列表上的指针,定义
端口功能 */
uint8_t * NumberOfPDO ; /*!< ListOfPDO 中定义的电源数据对象的数量
此参数必须设置为最大值 @ref USBPD_MAX_NB_PDO 值 */
} USBPD_PortPDO_TypeDef ;
/**
* @brief USBPD 端口 PDO 存储结构定义
*/
typedef struct
{
USBPD_PortPDO_TypeDef SourcePDO ; /*!< SRC 电源数据对象 */
} USBPD_PWR_Port_PDO_Storage_TypeDef ;
/* 用户代码结束 typedef */
6.5 usbpd_pwr_if.c中的修改
在/ USER CODE BEGIN-END Private_Variables / 标签之间添加以下代码:
/* USER CODE BEGIN Private_Variables */
/**
* @brief USBPD Port PDO Storage 数组声明
*/
USBPD_PWR_Port_PDO_Storage_TypeDef PWR_Port_PDO_Storage [ USBPD_PORT_COUNT ];
/* 用户代码结束 Private_Variables */
在/ USER CODE BEGIN-END USBPD_PWR_IF_Init / 标签之间添加以下代码:
/* 用户代码开始 USBPD_PWR_IF_Init */
USBPD_StatusTypeDef _status = USBPD_OK ;
/* 设置指向 PDO 值和端口 0 号的链接(在 H 文件的 PDO 数组中定义)。*/
PWR_Port_PDO_Storage [ USBPD_PORT_0 ]。来源 PDO 。ListOfPDO = ( uint32_t * ) PORT0_PDO_ListSRC ;
PWR_Port_PDO_Storage [ USBPD_PORT_0 ]。来源 PDO 。NumberOfPDO = & USBPD_NbPDO [ 1 ];
返回 _状态;
/* 用户代码结束 USBPD_PWR_IF_Init */
在/ USER CODE BEGIN-END USBPD_PWR_IF_SetProfile / 标签之间添加以下代码:
/* 用户代码开始 USBPD_PWR_IF_SetProfile */
USBPD_PDO_TypeDef _pdo ;
USBPD_SNKRDO_TypeDef _rdo ;
_rdo 。d32 = DPM_Ports [端口号]。DPM_RcvRequestDOMsg ;
_pdo 。d32 = PORT0_PDO_ListSRC [ 0 ];
返回 (bsp_error_none == bsp_usbpd_pwr_vbussetvoltage_fixed (portnum ,
_pdo。srcfixedpdo。voltagein50mvunits * 50 ,(_ rdo.rdo。_rdo。_rdo。fixiaiablerdo.firedvariablerdo.promertin10MANITS * 10 )_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /* 用户代码结束 USBPD_PWR_IF_SetProfile */
在/ USER CODE BEGIN-END USBPD_PWR_IF_GetPortPDOs / 标签之间添加以下代码:
/* 用户代码开始 USBPD_PWR_IF_GetPortPDOs */
uint32_t nbpdo , index , nb_valid_pdo = 0 ;
uint32_t * ptpdoarray = NULL ;
USBPD_PDO_TypeDef pdo_first ;
USBPD_PDO_TypeDef pdo ;
/* Check if valid port */
if (USBPD_PORT_IsValid(PortNum))
{
/* According to the type of PDO to be read, set the pointer on values and number of elements */
switch(DataId)
{
case USBPD_CORE_DATATYPE_SRC_PDO :
nbpdo = *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO;
ptpdoarray = PWR_Port_PDO_Storage[PortNum].SourcePDO.ListOfPDO;
/* Save the 1st PDO */
pdo_first.d32 = *ptpdoarray;
/* Reset un-chunked bit if current revision is PD2.0*/
if (USBPD_SPECIFICATION_REV2 == DPM_Params[PortNum].PE_SpecRevision)
{
pdo_first.SRCFixedPDO.UnchunkedExtendedMessage = USBPD_PDO_SRC_FIXED_UNCHUNK_NOT_SUPPORTED;
}
break;
default :
nbpdo = 0;
break;
}
/* Copy PDO data in output buffer */
for (index = 0; index < nbpdo; index++)
{
pdo.d32 = *ptpdoarray;
/* Copy only PDO (and not APDO in case of current revision is PD2.0) */
if ((USBPD_SPECIFICATION_REV2 == DPM_Params[PortNum].PE_SpecRevision)
&& (pdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_APDO))
{
}
else
{
/* Copy 1st PDO as potentially FRS or UNCHUNKED bits have been reset */
if (0 == index)
{
(void)memcpy(Ptr, (uint8_t*)&pdo_first.d32, 4u);
}
else
{
(void)memcpy((Ptr + (nb_valid_pdo * 4u)), (uint8_t*)ptpdoarray, 4u);
}
nb_valid_pdo++;
}
ptpdoarray++;
}
/* Set the number of read PDO (number of u32 elements); */
*Size = nb_valid_pdo;
}
/* USER CODE END USBPD_PWR_IF_GetPortPDOs */
Add the following code between the / USER CODE BEGIN-END USBPD_PWR_IF_SearchRequestedPDO / tags:
/* USER CODE BEGIN USBPD_PWR_IF_SearchRequestedPDO */
if((RdoPosition == 0) || (RdoPosition > *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO))
{
/* Invalid PDO index */
return USBPD_FAIL;
}
*Pdo = PWR_Port_PDO_Storage[PortNum].SourcePDO.ListOfPDO[RdoPosition - 1];
return USBPD_OK;
/* USER CODE END USBPD_PWR_IF_SearchRequestedPDO */
6.6 Modification in usbpd_dpm_user.c
Add the following code between the / USER CODE BEGIN-END Private_Variables / tags:
/* USER CODE BEGIN Private_Variables */
USBPD_HandleTypeDef DPM_Ports[USBPD_PORT_COUNT];
/* USER CODE END Private_Variables */
Add the following code between the / USER CODE BEGIN-END USBPD_USER_PRIVATE_FUNCTIONS_Prototypes / tags:
/* USER CODE BEGIN USBPD_USER_PRIVATE_FUNCTIONS_Prototypes */
static USBPD_StatusTypeDef DPM_TurnOnPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role);
static USBPD_StatusTypeDef DPM_TurnOffPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role);
/* USER CODE END USBPD_USER_PRIVATE_FUNCTIONS_Prototypes */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_UserInit / tags:
/* USER CODE BEGIN USBPD_DPM_UserInit */
/* PWR SET UP */
if(USBPD_OK != USBPD_PWR_IF_Init())
{
return USBPD_ERROR;
}
return USBPD_OK;
/* USER CODE END USBPD_DPM_UserInit */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_UserCableDetection / tags:
/* USER CODE BEGIN USBPD_DPM_UserCableDetection */
switch(State)
{
case USBPD_CAD_EVENT_ATTACHED:
case USBPD_CAD_EVENT_ATTEMC:
{
if (DPM_Params[PortNum].PE_PowerRole == USBPD_PORTPOWERROLE_SRC)
{
if (USBPD_OK != USBPD_PWR_IF_VBUSEnable(PortNum))
{
/* Should not occur */
osDelay(6000);
NVIC_SystemReset();
}
}
break;
}
case USBPD_CAD_EVENT_DETACHED :
case USBPD_CAD_EVENT_EMC :
default :
{
if (DPM_Params[PortNum].PE_PowerRole == USBPD_PORTPOWERROLE_SRC)
{
if (USBPD_OK != USBPD_PWR_IF_VBUSDisable(PortNum))
{
/* Should not occur */
while(1);
}
}
break;
}
}
/* USER CODE END USBPD_DPM_UserCableDetection */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_HardReset / tags:
/* USER CODE BEGIN USBPD_DPM_HardReset */
switch (Status)
{
case USBPD_HR_STATUS_WAIT_VBUS_VSAFE0V:
if (USBPD_PORTPOWERROLE_SRC == CurrentRole)
{
/* Reset the power supply */
DPM_TurnOffPower(PortNum, USBPD_PORTPOWERROLE_SRC);
}
break;
case USBPD_HR_STATUS_WAIT_VBUS_VSAFE5V:
if (CurrentRole == USBPD_PORTPOWERROLE_SRC)
{
/* Power on the power supply */
DPM_TurnOnPower(PortNum, CurrentRole);
}
break;
default:
break;
}
/* USER CODE END USBPD_DPM_HardReset */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_GetDataInfo / tags:
/* USER CODE BEGIN USBPD_DPM_GetDataInfo */
/* Check type of information targeted by request */
switch(DataId)
{
case USBPD_CORE_DATATYPE_REQ_VOLTAGE: /*!< Get voltage value requested for BIST tests, expect 5V */
*Size = 4;
(void)memcpy((uint8_t*)Ptr, (uint8_t *)&DPM_Ports[PortNum].DPM_RequestedVoltage, *Size);
break;
case USBPD_CORE_DATATYPE_SRC_PDO: /*!< Handling of port Source PDO */
USBPD_PWR_IF_GetPortPDOs(PortNum, DataId, Ptr, Size);
*Size *= 4;
break;
// case USBPD_CORE_PPS_STATUS: /*!< PPS Status message content */
// break;
// case USBPD_CORE_SNK_EXTENDED_CAPA: /*!< Retrieve of Sink Extended capability message content */
// break;
// case USBPD_CORE_INFO_STATUS: /*!< Information status message content */
// break;
// case USBPD_CORE_MANUFACTURER_INFO: /*!< Retrieve of Manufacturer info message content */
// break;
// case USBPD_CORE_BATTERY_STATUS: /*!< Retrieve of Battery status message content */
// break;
// case USBPD_CORE_BATTERY_CAPABILITY: /*!< Retrieve of Battery capability message content */
// break;
default:
DPM_USER_DEBUG_TRACE(PortNum, "ADVICE: update USBPD_DPM_GetDataInfo:%d", DataId);
break;
}
/* USER CODE END USBPD_DPM_GetDataInfo */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_SetDataInfo / tags:
/* USER CODE BEGIN USBPD_DPM_SetDataInfo */
/* Check type of information targeted by request */
switch(DataId)
{
case USBPD_CORE_DATATYPE_RDO_POSITION: /*!< Reset the PDO position selected by the sink only */
if (Size == 4)
{
uint8_t* temp;
temp = (uint8_t*)&DPM_Ports[PortNum].DPM_RDOPosition;
(void)memcpy(temp, Ptr, Size);
DPM_Ports[PortNum].DPM_RDOPositionPrevious = *Ptr;
temp = (uint8_t*)&DPM_Ports[PortNum].DPM_RDOPositionPrevious;
(void)memcpy(temp, Ptr, Size);
}
break;
// case USBPD_CORE_DATATYPE_RCV_SRC_PDO: /*!< Storage of Received Source PDO values */
// break;
// case USBPD_CORE_DATATYPE_RCV_SNK_PDO: /*!< Storage of Received Sink PDO values */
// break;
case USBPD_CORE_DATATYPE_RCV_REQ_PDO : /*!< Storage of Received Sink Request PDO value */
if (Size == 4)
{
memcpy((uint8_t *)&DPM_Ports[PortNum].DPM_RcvRequestDOMsg, Ptr, 4);
}
break;
// case USBPD_CORE_INFO_STATUS: /*!< Information status message content */
// break;
// case USBPD_CORE_ALERT: /*!< Storing of received Alert message content */
// break;
// case USBPD_CORE_GET_MANUFACTURER_INFO: /*!< Storing of received Get Manufacturer info message content */
// break;
// case USBPD_CORE_GET_BATTERY_STATUS: /*!< Storing of received Get Battery status message content */
// break;
// case USBPD_CORE_GET_BATTERY_CAPABILITY: /*!< Storing of received Get Battery capability message content*/
// break;
// case USBPD_CORE_SNK_EXTENDED_CAPA: /*!< Storing of Sink Extended capability message content */
// break;
default:
DPM_USER_DEBUG_TRACE(PortNum, "ADVICE: update USBPD_DPM_SetDataInfo:%d", DataId);
break;
}
/* USER CODE END USBPD_DPM_SetDataInfo */
Add the following code between the / USER CODE BEGIN-END USBPD_DPM_EvaluateRequest / tags:
/* USER CODE BEGIN USBPD_DPM_EvaluateRequest */
USBPD_StatusTypeDef _retr = USBPD_REJECT;
USBPD_PDO_TypeDef pdo;
USBPD_SNKRDO_TypeDef rdo;
/* read the request value received */
rdo.d32 = DPM_Ports[PortNum].DPM_RcvRequestDOMsg;
/* Search PDO in Port Source PDO list, that corresponds to Position provided in Request RDO */
if (USBPD_PWR_IF_SearchRequestedPDO(PortNum, rdo.GenericRDO.ObjectPosition, &pdo.d32) == USBPD_OK)
{
/* Evaluate the request */
if(pdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED)
{
if((rdo.FixedVariableRDO.OperatingCurrentIn10mAunits > pdo.SRCFixedPDO.MaxCurrentIn10mAunits)
|| (rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits > pdo.SRCFixedPDO.MaxCurrentIn10mAunits))
{
/* Sink requests too much maximum operating current */
/* USBPD_DPM_EvaluateRequest: Sink requests too much maximum operating current */
_retr = USBPD_REJECT;
}
else
{
/* Save the power object */
*PtrPowerObject = pdo.GenericPDO.PowerObject;
/* Set RDO position and requested voltage in DPM port structure */
DPM_Ports[PortNum].DPM_RequestedVoltage = pdo.SRCFixedPDO.VoltageIn50mVunits * 50;
DPM_Ports[PortNum].DPM_RDOPositionPrevious = DPM_Ports[PortNum].DPM_RDOPosition;
DPM_Ports[PortNum].DPM_RDOPosition = rdo.GenericRDO.ObjectPosition;
_retr = USBPD_ACCEPT;
}
}
}
return _retr;
/* USER CODE END USBPD_DPM_EvaluateRequest */
Add the following code between the / USER CODE BEGIN-END USBPD_USER_PRIVATE_FUNCTIONS / tags:
/* USER CODE BEGIN USBPD_USER_PRIVATE_FUNCTIONS */
/**
* @brief Turn Off power supply.
* @param PortNum The current port number
* @param Role Port power role
* @retval USBPD_OK, USBPD_ERROR
*/
static USBPD_StatusTypeDef DPM_TurnOffPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
{
USBPD_StatusTypeDef status;
status = USBPD_PWR_IF_VBUSDisable(PortNum);
return status;
}
/**
* @brief Turn On power supply.
* @param PortNum The current port number
* @param Role Port power role
* @retval USBPD_ACCEPT, USBPD_WAIT, USBPD_REJECT
*/
static USBPD_StatusTypeDef DPM_TurnOnPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
{
USBPD_StatusTypeDef status;
/* Enable the output */
status = USBPD_PWR_IF_VBUSEnable(PortNum);
return status;
}
/* USER CODE END USBPD_USER_PRIVATE_FUNCTIONS */
-
usb
+关注
关注
60文章
7896浏览量
263988 -
PD
+关注
关注
4文章
466浏览量
43928
发布评论请先 登录
相关推荐
评论