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文章
7952瀏覽量
264935 -
PD
+關注
關注
4文章
475瀏覽量
44012
發布評論請先 登錄
相關推薦
評論