介绍 HUSB238
简介:USB PD受电端芯片(PD Sink,也叫PD诱骗芯片)
描述:HUSB238是一款高度集成的USB PD受电端芯片(PD Sink,也叫PD诱骗芯片)。传输的额定功率可达100W。它兼容PD3.0 V1.3和Type-C V1.4。它还可以支持BC1.2 DCP、CDP和SDP和Apple 5V2.4A充电协议。这种方案也被称为桶形连接器替换(Barrel Connector Replacement),旨在替代传统的桶形连接器和DC插座(DC JACK)。HUSB238已经获得USB-IF认证,TID3666。它可以用于具有传统桶形连接器或USB micro-B电源连接器的电子设备,如物联网设备、无线充电器、无人机、智能扬声器、电动工具和其他设备。 HUSB238采用DFN-10L封装和SOT33-6L封装。
特性: USB-IF 认证 TID 3666 • 设备端USB PD sink控制器 • 支持Type-C 1.4 & USB PD3.0标准 n 可配置Rd n 支持死电池 • 传统的USB受电设备 n BC1.2 SDP, CDP和DCP检测 n Apple Divider 3检测 • 3.0至25V工作电压范围, • VIN, GATE最高耐压30V • CC1和CC2引脚25V高压保护 • 外部电阻网络设置动态申请电流电压值(VSET & ISET) • I2C 通信实现高级PDO申请 • Cable应用可模拟eMarker功能,适用于电流大于3A应用 • 集成负载开关驱动,可驱动PMOS或者负载开关芯片 • VBUS过压和欠压保护 • 过温保护,过温保护门限可配置 • 低功耗 • DFN-10L 和SOT33-6L封装形式 • 工作温度范围:-40°C - 125°C技术文档
以下是使用该芯片的时候的一些记录和IIC寄存器的资料,数据手册网上找不到的可以私信联系我免费发
使用的时候对IIC数据进行解析输出如下
网上很少关于该芯片IIC寄存器方面的描述在这里附上
ESP-IDF v4.4环境下的驱动
HUSB238Driver.h
#ifndef __HUSB238_H__ #define __HUSB238_H__ #include <esp_log.h> #define HUSB238_I2CAddress (uint8_t)(0x08) /// @brief HUSB238 寄存器地址 enum HUSB238_reg_addr { Reg_PD_STATUS0 = 0x00, Reg_PD_STATUS1, Reg_SRC_PDO_5V, Reg_SRC_PDO_9V, Reg_SRC_PDO_12V, Reg_SRC_PDO_15V, Reg_SRC_PDO_18V, Reg_SRC_PDO_20V, Reg_SRC_PDO_SEL, Reg_GO_COMMAND, }; /// @brief 寄存器电流对应值 typedef enum { PD_0_5A = 0x00, PD_0_7A, PD_1_0A, PD_1_25A, PD_1_5A, PD_1_75A, PD_2A, PD_2_25A, PD_2_5A, PD_2_75A, PD_3A, PD_3_25A, PD_3_5A, PD_4A, PD_4_5A, PD_5A, } HUSB238_CURRENT_e; /// @brief 写入 SRC_PDO(0x08) 设置输出电压用到 typedef enum { Not_sel = 0x0, PDO_5V = 0x1, PDO_9V = 0x2, PDO_12V = 0x3, PDO_15V = 0x8, PDO_18V = 0x9, PDO_20V = 0xa, } HUSB238_SELECT_Voltage_e; /// @brief 读取 STATUS0(0x00) 状态寄存器值用到 typedef enum { Voltage_unknown = 0x0, Voltage_5V, Voltage_9V, Voltage_12V, Voltage_15V, Voltage_18V, Voltage_20V, } HUSB238_Voltage_e; /// @brief 命令 enum HUSB238_CMD { Request_PDO = 0b00001, Get_SRC_Cap = 0b00100, Hard_Reset = 0b10000, }; typedef union { struct { HUSB238_CURRENT_e PD_SRC_CURRENT : 4; HUSB238_Voltage_e PD_SRC_VOLTAGE : 4; } bit; uint8_t all; } HUSB238_Reg_PD_STATUS0; typedef union { struct { uint8_t CURRENT_5V : 2; uint8_t VOLTAGE_5V : 1; uint8_t PD_RESPONSE : 3; uint8_t ATTACH : 1; uint8_t CC_DIR : 1; } bit; uint8_t all; } HUSB238_Reg_PD_STATUS1; typedef union { struct { HUSB238_CURRENT_e SRC_CURRENT : 4; uint8_t RESERVED : 3; uint8_t SRC_DETECTED : 1; } bit; uint8_t all; } HUSB238_Reg_SRC_PDO; typedef union { struct { uint8_t RESERVED : 4; HUSB238_SELECT_Voltage_e PDO_SELECT : 4; } bit; uint8_t all; } HUSB238_Reg_SRC_PDO_SEL; typedef struct { HUSB238_Reg_PD_STATUS0 PD_STATUS0; HUSB238_Reg_PD_STATUS1 PD_STATUS1; HUSB238_Reg_SRC_PDO SRC_PDO_5V; HUSB238_Reg_SRC_PDO SRC_PDO_9V; HUSB238_Reg_SRC_PDO SRC_PDO_12V; HUSB238_Reg_SRC_PDO SRC_PDO_15V; HUSB238_Reg_SRC_PDO SRC_PDO_18V; HUSB238_Reg_SRC_PDO SRC_PDO_20V; HUSB238_Reg_SRC_PDO_SEL SRC_PDO; uint8_t GO_COMMAND; } HUSB238_reg_t; typedef struct { bool detected; float current; uint16_t voltage; } HUSB238_Capability_t; /// @brief 初始化 /// @param sda sda /// @param scl scl void HUSB238_Init(int sda, int scl); /// @brief regs 寄存器值 转化可输出能力列表 /// @param regs 大小为 10 /// @param pdoList 大小为 6 ! void HUSB238_ExtractCap(HUSB238_Capability_t *pdoList); /// @brief 获取当前PD输出能力 /// @param voltage /// @param current void HUSB238_GetCapabilities(uint16_t *voltage, float *current); void HUSB238_GetCurrentMode(HUSB238_Voltage_e *voltage, HUSB238_CURRENT_e *current); void HUSB238_SelVoltage(HUSB238_SELECT_Voltage_e voltage); /// @brief 读取到的电压寄存器值转化电压值 /// @param voltage 从 STATUS0(0x00) 读取到的电压值 /// @return 电压值 uint16_t HUSB238_Voltage2PDO(HUSB238_Voltage_e voltage); /// @brief 转化寄存器电流对应值 /// @param c 被转化的电流寄存器值 /// @return 返回电流值 float to_current(HUSB238_CURRENT_e c); /// @brief 硬复位 void HUSB238_HardReset(); // 读取全部数据 void HUSB238_ReadAllReg(uint8_t *regs); #endif /* __HUSB238_H */
HUSB238Driver.c
#include <string.h> #include "HUSB238Driver.h" #include "driver/i2c.h" bool initlized = false; // 电压值 uint16_t votlage_Table[] = {0, 5, 9, 12, 15, 18, 20}; // 电流值 float current_Table[] = {0.5f, 0.7f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.25f, 2.5f, 2.75f, 3.0f, 3.25f, 3.5f, 4.0f, 4.5f, 5.0f}; #define I2C_NUM I2C_NUM_0 /*!< I2C port number for master dev */ #define I2C_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */ #define I2C_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */ #define I2C_FREQ_HZ 100000 // 400000 /*!< I2C master clock frequency */ #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ #define ACK_CHECK_EN 1 /*!< I2C master will check ack from slave*/ #define ACK_CHECK_DIS 0 /*!< I2C master will not check ack from slave */ #define ACK_VAL (i2c_ack_type_t)0 /*!< I2C ack value */ #define NACK_VAL (i2c_ack_type_t)1 /*!< I2C nack value */ #define DEBUG_LOG false /*是否日志输出*/ /// @brief I2C 读取多个寄存器值 /// @param slaveAddr 从机地址 /// @param startAddress 开始地址 /// @param nBytesRead 字节数 /// @param data 读取缓存 /// @return int IRAM_ATTR HUSB238_I2CReadBytes(uint8_t slaveAddr, uint8_t startAddress, uint16_t nBytesRead, uint8_t *data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, slaveAddr << 1 | WRITE_BIT, ACK_CHECK_EN); i2c_master_write_byte(cmd, startAddress, ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, slaveAddr << 1 | READ_BIT, ACK_CHECK_EN); if (nBytesRead > 1) i2c_master_read(cmd, data, nBytesRead - 1, ACK_VAL); i2c_master_read_byte(cmd, data + nBytesRead - 1, NACK_VAL); i2c_master_stop(cmd); int ret = i2c_master_cmd_begin(I2C_NUM, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); return ret; } /// @brief I2C写入寄存器值 /// @param slaveAddr 从机地址 /// @param writeAddress 写入寄存器地址 /// @param data 写入的数据 /// @return int IRAM_ATTR HUSB238_WriteReg(uint8_t slaveAddr, uint8_t writeAddress, uint8_t data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (slaveAddr << 1) | WRITE_BIT, ACK_CHECK_EN); i2c_master_write_byte(cmd, writeAddress, ACK_CHECK_EN); i2c_master_write_byte(cmd, data, ACK_CHECK_EN); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_NUM, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); static uint8_t dataCheck; HUSB238_I2CReadBytes(slaveAddr, writeAddress, 1, &dataCheck); if (dataCheck != data) return -2; return ret; } /// @brief 发送Get_SRC_Cap命令 void HUSB238_RefreshSrcCap() { uint8_t cmd = Get_SRC_Cap; HUSB238_WriteReg(HUSB238_I2CAddress, Reg_GO_COMMAND, cmd); } /// @brief 读取 HUSB238 全部寄存器数据 /// @param regs 大小为 10 的 uint8_t 类型数组 void HUSB238_ReadAllReg(uint8_t *regs) { memset(regs, 0, 10); HUSB238_I2CReadBytes(HUSB238_I2CAddress, 0x00, 10, (uint8_t *)regs); if(DEBUG_LOG){ printf("\nHUSB238_ReadAllReg:\n"); for(int i = 0; i < 10; i++){ printf("0x%02x: 0x%02x \n", i, regs[i]); } printf("\n"); } } /// @brief regs 寄存器值 转化可输出能力列表 /// @param regs 大小为 10 /// @param pdoList 大小为 6 ! void HUSB238_ExtractCap(HUSB238_Capability_t *pdoList) { uint8_t regs[10], have = 0; if (!pdoList) { return; } HUSB238_ReadAllReg(regs); HUSB238_Reg_SRC_PDO *reg; HUSB238_Capability_t cap; for (int i = 0; i < 6; i++) { reg = (HUSB238_Reg_SRC_PDO *)(regs + i + 2); // memcpy(®, ®s[i + 2], sizeof(uint8_t)); // reg = static_cast<HUSB238_Reg_SRC_PDO>(regs[i + 2]); if (reg->bit.SRC_DETECTED){ HUSB238_CURRENT_e current = reg->bit.SRC_CURRENT; cap.detected = true; cap.current = to_current(current); have = 1; }else{ cap.detected = false; } cap.voltage = HUSB238_Voltage2PDO((HUSB238_Voltage_e)(i + 1)); pdoList[i] = cap; } if(DEBUG_LOG && have == 1){ printf("\n输出能力列表:\n"); for(int i = 0; i < 6; i++){ if(pdoList[i].detected == true){ printf("| 输出电压: %dV | 输出电流: %.2fA\n", pdoList[i].voltage, pdoList[i].current); } } printf("\n"); } } /// @brief 获取当前PD输出能力 /// @param voltage 电压 单位 'V' /// @param current 电流 单位 'A' void HUSB238_GetCapabilities(uint16_t *voltage, float *current) { HUSB238_Voltage_e voltage_e; HUSB238_CURRENT_e current_e; HUSB238_RefreshSrcCap(); vTaskDelay( 500 / portTICK_PERIOD_MS ); HUSB238_GetCurrentMode(&voltage_e, ¤t_e); *voltage = HUSB238_Voltage2PDO(voltage_e); if(*voltage != 0){ *current = to_current(current_e); }else{ *current = 0; } if(DEBUG_LOG){ printf("\n当前输出能力\n电压值:%dV\n电流值:%.2fA\r\n", *voltage, *current); } } /// @brief 请求PDO输出 void HUSB238_RequestPDO() { uint8_t cmd = Request_PDO; HUSB238_WriteReg(HUSB238_I2CAddress, Reg_GO_COMMAND, cmd); } /// @brief 硬复位 void HUSB238_HardReset() { uint8_t cmd = Hard_Reset; HUSB238_WriteReg(HUSB238_I2CAddress, Reg_GO_COMMAND, cmd); } /// @brief 初始化 /// @param sda sda /// @param scl scl void HUSB238_Init(int sda, int scl) { i2c_port_t i2c_master_port = I2C_NUM; i2c_config_t conf; conf.mode = I2C_MODE_MASTER; conf.sda_io_num = sda; conf.sda_pullup_en = GPIO_PULLUP_DISABLE; conf.scl_io_num = scl; conf.scl_pullup_en = GPIO_PULLUP_DISABLE; conf.master.clk_speed = I2C_FREQ_HZ; conf.clk_flags = 0; i2c_param_config(i2c_master_port, &conf); i2c_driver_install(i2c_master_port, conf.mode, I2C_RX_BUF_DISABLE, I2C_TX_BUF_DISABLE, 0); initlized = true; } /// @brief 设置PD电压值 /// @param pdo 设置的电压(HUSB238_SELECT_Voltage_e) void HUSB238_SelVoltage(HUSB238_SELECT_Voltage_e pdo) { HUSB238_Reg_SRC_PDO_SEL targetPDO; targetPDO.all = 0xA; targetPDO.bit.PDO_SELECT = pdo; HUSB238_WriteReg(HUSB238_I2CAddress, Reg_SRC_PDO_SEL, targetPDO.all); HUSB238_RequestPDO(); } /// @brief 读取PD当前状态寄存器值 /// @param voltage 电压状态值 /// @param current 电流状态值 void HUSB238_GetCurrentMode(HUSB238_Voltage_e *voltage, HUSB238_CURRENT_e *current) { uint8_t reag[2] = {0}; HUSB238_Reg_PD_STATUS0 status0; HUSB238_Reg_PD_STATUS1 status1; HUSB238_I2CReadBytes(HUSB238_I2CAddress, 0x00, 2, (uint8_t *)&reag); ((uint8_t *)&status0)[0] = reag[0]; ((uint8_t *)&status1)[0] = reag[1]; if(DEBUG_LOG){ printf("status0.all = 0x%x\n", status0.all); printf("status1.all = 0x%x\n", status1.all); } *current = status0.bit.PD_SRC_CURRENT; *voltage = status0.bit.PD_SRC_VOLTAGE; } /// @brief 读取到的电压寄存器值转化电压值 /// @param voltage 从 STATUS0(0x00) 读取到的电压值 /// @return 电压值 uint16_t HUSB238_Voltage2PDO(HUSB238_Voltage_e voltage) { if(DEBUG_LOG){ printf("voltage: %d => %d\n", voltage, votlage_Table[voltage]); } return votlage_Table[voltage]; } /// @brief 转化寄存器电流对应值 /// @param c 被转化的电流寄存器值 /// @return 返回电流值 float to_current(HUSB238_CURRENT_e c) { uint8_t i = c & 0xf; if (i <= PD_5A) { if(DEBUG_LOG){ printf("current: %d => %.2f\n", c, current_Table[i]); } return current_Table[i]; } else { if(DEBUG_LOG){ printf("current: %d => %.2f\n", c, 0.0f); } return 0.0f; } }
使用示例
// PD 芯片相关变量 uint16_t PD_Voltage; float PD_Current; void deal_vTask( void * arg ){ // HUSB238_1 Init printf("HUSB238_Init\n"); HUSB238_Init(23, 22); HUSB238_Capability_t PDCapabilities[6]; for( ;; ){ // 获取当前输出电压电流值 HUSB238_GetCapabilities(&PD_Voltage, &PD_Current); // 获取供电能力列表 HUSB238_ExtractCap(PDCapabilities); printf("\n输出能力列表:\n"); for(int i = 0; i < 6; i++){ if(PDCapabilities[i].detected == true){ printf("| 输出电压: %dV | 输出电流: %.2fA\n", PDCapabilities[i].voltage, PDCapabilities[i].current); } } printf("\n"); vTaskDelay( 1000 / portTICK_PERIOD_MS ); } }
硬件原理图
注意该粗的线要粗呢
因篇幅问题不能全部显示,请点此查看更多更全内容
怀疑对方AI换脸可以让对方摁鼻子 真人摁下去鼻子会变形
女子野生动物园下车狼悄悄靠近 后车司机按喇叭提醒
睡前玩8分钟手机身体兴奋1小时 还可能让你“变丑”
惊蛰为啥吃梨?倒春寒来不来就看惊蛰
男子高速犯困开智能驾驶出事故 60万刚买的奔驰严重损毁