This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] BQ76PL536A:SPI 通信

Guru**** 2322270 points
Other Parts Discussed in Thread: BQ76PL536A
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/594004/bq76pl536a-spi-communication

器件型号:BQ76PL536A

我`m 2个 BQ76PL536A 来管理5个电池。 `m 与电路板通信、我使用 Arduino Uno。 `s I`m 使用以下代码:

#include 
#include 

//
// teste com dois 卡通
//

const 字节 crcTable[256]={
0x00、0x07、0x0E、0x09、0x1C、 0x1b、0x12、0x15、0x38、0x3F、 0x36、0x31、0x24、0x23、0x2A、
0x2D、0x70、0x77、0x7E、0x79、 0x6C、0x6B、0x62、0x65、0x48、 0x4F、0x46、0x41、0x54、0x53、 0x5A、0x5D、
0xE0、0xE7、0xEE、 0xE9、0xFC、0xFB、0xF2、0xf5、 0xD8、0xDF、0xD6、0xD1、0xC4、 0xC3、0xCA、0xCD、0x90、
0x97、 0x9E、0x99、0x8C、0x8B、0x82、 0x85、0xA8、0xAF、0xA6、0xA1、 0xB4、0xB3、0xBA、0xBD、0xC7、 0xC0、
0xC9、0xCE、0xDB、0xDC、 0xD5、0xD2、0xFF、0xf8、0xF1、 0xF6、0xE3、0xE4、0xED、0xEA、 0xB7、0xB0、0xB9、
0xBE、0xAB、 0xAC、0xA5、0xA2、0x8F、0x88、 0x81、0x86、0x93、0x94、0x9D、 0x9A、0x27、0x20、0x29、0x2E、
0x3B、0x3C、0x35、0x32、0x1F、 0x18、0x11、0x16、0x03、0x04、 0x0D、0x0A、0x57、0x50、0x59、 0x5E、0x4B、
0x4C、0x45、0x42、 0x6f、0x68、0x61、0x66、0x73、 0x74、0x7D、0x7A、0x89、0x8E、 0x87、0x80、0x95、0x92、
0x9B、 0x9C、0xB1、0xB6、0xBF、0xB8、 0xAD、0xAA、0xA3、0xA4、0xF9、 0xFE、0xF7、0xF0、0xE5、0xE2、 0xEB、
0xEC、0xC1、0xC6、0xCF、 0xC8、0xDD、0xDA、0xD3、0xD4、 0x69、0x6E、0x67、0x60、0x75、 0x72、0x7B、0x7C、
0x51、0x56、 0x5F、0x58、0x4D、0x4A、0x43、 0x44、0x19、0x1E、0x17、0x10、 0x05、0x02、0x0B、0x0C、0x21、
0x26、0x2F、0x28、0x3D、0x3A、 0x33、0x34、0x4E、0x49、0x40、 0x47、0x52、0x55、0x5C、0x5B、 0x76、0x71、
0x78、0x7F、0x6A、 0x6D、0x64、0x63、0x3E、0x39、 0x30、0x37、0x22、0x25、0x2C、 0x2B、0x06、0x01、0x08、
0x0F、 0x1A、0x1D、0x14、0x13、0xAE、 0xA9、0xA0、0xA7、0xB2、0xB5、 0xBC、0xBB、0x96、0x91、0x98、 0x9F、
0x8A、0x8D、0x84、0x83、 0xDE、0xD9、0xD0、0xD7、0xC2、 0xC5、0xCC、0xCB、0xE6、0xE1、 0xE8、0xEF、0xFA、
0xFD、0xF4、 0xF3
};

#define DEVICE_STATUS 0x00
#define GPAI 0x01
#define VCELL1 0x03
#define VCELL2 0x05
#define VCELL3 0x07
#define VCELL4 0x09
#define VCELL5 0x0B
#define VCELL6 0x0D
#define Temperature1 0x0F
#define TEMPRATURE2 0x11
#define ALERT_STATUS 0x20
#define FAULT_STATUS 0x21
#define COV_FAULT 0x22
#define CUV_FAULT 0x23
#define PRESULT_A 0x24
#define PRESULT_B 0x25
#define ADC_CONTROL 0x30
#define IO_CONTROL 0x31
#define CB_CTRL 0x32
#define CB_TIME 0x33
#define ADC_convert 0x34
#define Shdw_CTRL 0x3A
#define ADDRESS_CONTROL 0x3B
#define RESET 0x3C
#define TEST_SELECT 0x3D
#define E_EN 0x3F
#define FUNCING_CONFIG 0x40
#define IO_CONFIG 0x41


#define ALERT_PIN 3
#define FAULT_PIN 4
#define CONV_PIN 5
#define DRDY_PIN 6
#define SLAVE_SELECT_PIN 10
#define MOSI11
#define MISO12

#define DISCOVERY_ADDR 0x00
#define broadcast 0x3F
#define ADDRESS_MAP 0x3F
#define AC_ADDR_RQST 0x80
#define RESET_COMMAND 0xA5

#define dev1 1
#define dev2 2

静态 int devices_used = 2;

void setup();
void loop();

void setup(){
//编程
延迟延迟(2000);
pinMode (slave_select_PIN、输出);
pinMode (fault_PIN、输入);
引脚模式(ALERT_PIN、输入);
引脚模式(DRDY_PIN、输入);
引脚模式(CONV_PIN、 输出);

//写入初始引脚状态

digitalWrite (CONV_PIN、low);
digitalWrite (slave_select_PIN、HIGH);

//开始串行通信以进行串行调试
Serial.begin(57600);
delay (100);

//设置 SPI 首选项
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV32);
SPI.setBitOrder(MSBFIRST);

//连接到 BMS SHIELD
setupDevices();
}


void loop (){

delay (1000);
}

void setupDevices()
{
int num_dev;

num_dev=setAddresses();

if (num_dev == devices_used )
{ Serial.print ("Found all ");Serial.print (nnum_dev);
serial.println ("设备。");
}
否则
serial.println ("查找设备时出错...");
}


int setAddresses(){

字节 lear_for=0;
字节 n;
字节 temp;
byte* verify;
int mystatus;

serial.println ("初始化设备");
执行
{
bqWrite (广播、RESET、RESET_COMMAND);
查找++;
N=0;
操作
{
N++;
bqWrite (discovery_ADDR、address_control、n);
*verify_bqRead (n、address_control、1);

//验证 ADDRESS_CONTROL 的位7是否设置正确
temp=(* verify)& ac_ADDR_RQST;

如果(temp!= 0)
{Serial.print ("bit 7 ADRRESS_control set OK=");Serial.println (temp);
serial.print("Addrres=");serial.println(*verify & address_map);
}
其他
{Serial.println ("错误:位7 (ADRRESS_CONTROL)未设置。");
serial.print("Verify=");serial.println(*verify);
serial.print("Address stored=");serial.println(*verify & address_map);
返回 n-1;
}
} while (n < lare_for);
}while (n < device_used);
return n;
}


void bqWrite (byte deviceAddress、byte regAddress、byte regData){
SPI.setDataMode(SPI_MODE1);

//移位器件位并设置位0
字节 logicalAddress = deviceAddress << 1;
logicalAddress |= 1 << 0; //设置位0、测试位集(x、n)

字节 crcInput[3]={
logicalAddress、regAddress、regData
};

//将 SS 引脚置于低电平以选择芯片
digitalWrite (slave_select_PIN、low);

//发送和接收 SPI
spi.transfer (logicalAddress);
spi.transfer (regAddress);
spi.transfer (regData);
spi.transfer (pec (crcInput));

//采用
SPI .digbyte





SPI.setDataMode(SPI_MODE1);(regbyte);SPI.setDataMode(SPI_MODE0);选择芯片高字节从器件地址;degbyte (regbyte)

//移动器件位并清除位0
字节逻辑地址= deviceAddress << 1;
logicalAddress &=~(1 <<0);//清除位0、测试 bitClear (x、n)

//创建用于接收数据的缓冲区并清除静态
字节接收数据[20];
memset (sizeData、0、receiveof (

ss)://选择低字节接收数据;//将芯片选为低字节
digitalWrite (slave_select_PIN、low);

//发送和接收 SPI
spi.transfer (logicalAddress);
spi.transfer (regAddress);
spi.transfer (length);
for (int i = 0;i < length + 1;i++){
receivedData[i]= SPI.transfer (0x00);
}

//将 SS 引脚置为高电平来取消选择芯片:
digitalWrite (slave_select_PIN、HIGH);

SPI.setDataMode(SPI_MODE0);

//从寄存器读取的数据
返回 receivedData;
}

字节 PEC (byte crcBuffer[]){
byte CRC = 0;
int temp = 0;
for (i < 1 + creBuffer);for (i < 1 + i +(cre+)
temp = CRC ^ crcBuffer[i];
CRC = crcTable[temp];
}
返回 CRC;
} 

遗憾的是、我甚至无法正确设置器件地址。 在输出下方、我得到:

===========================

正在初始化设备。
错误:位7 (ADRRESS_CONTROL)未设置。
验证=61
地址存储= 61
查找设备时出错...
===========================

是否有任何关于从何处开始调试的建议?

非常感谢、

Cesar。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Cesar、


    www.ti.com/.../slaa478.pdf

    转到此应用手册、您将找到 Pl536A 的实际代码。

    请看一下。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Roger 的指导! 但是、在购买另一个微控制器之前、我想向您展示一下我之前进行的测试是什么。 这`m 我只使用一个 pl536a、而北通信是浮动的。 我在一组串联电阻上使用了可变电压、以仿真5节电池的电压。 这次的代码是:

    #include 
    #include 
    
    const 字节 crcTable[256]={
    0x00、0x07、0x0E、0x09、0x1C、0x1B、0x12、0x15、0x38、0x3F、0x36、0x31、0x23、0x2A、
    0x2D、0x70、0x77、0x7E、0x79、0x6B、0x62、0x65、48、0xB、0xB
    
    
    、0xB、0x4、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0x4、0xB、0xB、0xB、0xB、0xB、0xB、0x
    
    
    
    
    0xEC、0xAB、0xAC、0xA5、0xA2、0x8F、0x88、0x81、0x86、0x93、0x94、0x9D、0x27、0x20、0x29、0x2E、0x3B、0x35、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0x7、0xB
    0x51、0x56、0x5F、0x58、0x4D、0x4A、0x43、0xCB 0x19、0x1E、0x17、0x10、0x0B、0x0C、0x21、
    0x26、0x2F、0x28、0x3D、0x3A、0x33、0x34、0x4E、0x49、0x40、0x47、0x52、55、0x5C、0x9
    、0x7、0x7、0xB
    、0x7、0x7、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0x9、0x7、0x7、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0xB、0x9、0xB、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0x7、0xB、0xB、0x9、0xB、0xB、0xB、0xB
    
    0xFD、0xF4、0xF3};
    
    #define DEVICE_STATUS 0x00
    #define GPAI 0x01
    #define VCELL1 0x03
    #define VCELL2 0x05
    #define VCELL3 0x07
    #define VCELL4 0x09
    #define VCELL5 0x0B
    #define VCELL6 0x0D
    #define Temperature1 0x0F
    #define TEMPRATURE2 0x11
    #define ALERT_STATUS 0x20
    #define FAULT_STATUS 0x21
    #define COV_FAULT 0x22
    #define CUV_FAULT 0x23
    #define PRESULT_A 0x24
    #define PRESULT_B 0x25
    #define ADC_CONTROL 0x30
    #define IO_CONTROL 0x31
    #define CB_CTRL 0x32
    #define CB_TIME 0x33
    #define ADC_convert 0x34
    #define Shdw_CTRL 0x3A
    #define ADDRESS_CONTROL 0x3B
    #define RESET 0x3C
    #define TEST_SELECT 0x3D
    #define E_EN 0x3F
    #define FUNCING_CONFIG 0x40
    #define IO_CONFIG 0x41
    
    
    #define ALERT_PIN 3
    #define FAULT_PIN 4
    #define CONV_PIN 6
    #define DRDY_PIN 7
    #define SLAVE_SELECT_PIN 10
    
    #define DEV1 1
    
    
    void setup();
    void loop();
    
    void setup(){
    //编程延迟延迟延迟(
    2000);
    
    //设置引脚模式和中断
    引脚模式(SLAVE_SELECT_PIN、输出);
    引脚模式(FAULT_PIN、输入);
    引脚模式(ALERT_PIN、 输入);
    pinMode (DRDY_PIN、输入);
    pinMode (CONV_PIN、输出);
    
    //写入初始引脚状态
    digitalWrite (CONV_PIN、low);
    digitalWrite (slave_select_PIN、high);
    
    //开始串行通信以进行串行调试
    Serial.begin(57600);
    delay (100);
    
    //设置 SPI 首选项
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV32);
    SPI.setBitOrder(MSBFIRST);
    
    //连接到 BMS shield
    setupDevices ();
    
    }
    
    
    void loop (){
    double volt_cell;
    
    getCellVoltage=CellVoltage (1);
    getcell (1)
    
    ;getcell (Serial);getvoltalt (alt);getcell (1);getcell (alt);getvoltle.print (alt);
    serial.print ("v2=");serial.println (volt_cell);
    
    volt_cell=getCellVoltage (3);
    serial.print ("v3=");serial.println (volt_cell);
    
    VOLT_CELL=getCellVoltage (4);
    Serial.print ("v4=");Serial.println (VOLT_CELL);
    
    VOLT_CELL=getCellVoltage (5);
    Serial.print ("v5="); serial.println (volt_cell);
    
    serial.println ("================================================================================ ");
    delay (1000);
    }
    
    void setupDevices(){
    
    setAddresses();
    delay (10);
    
    bqWrite (0x01、ADC_CONTROL、0x04);
    delay (10);
    }
    
    
    void setAddes(){
    //将底部地址设置为1
    
    bqWrite (0x3F、RESET、0xA5);
    bqWrite (0x00、address_control
    
    
    (0x80
    );*resert (1);*如果是1)、则为1)
    serial.println ("写入地址时出错!");
    否则
    serial.println ("无写入地址!");
    * addr = bqRead (dev1、address_control、0x01);
    * addr=(* addr)& 0x3F;
    Serial.print ("存储的地址:");Serial.println (* addr);
    
    delay (4000);
    }
    
    double getCellVoltage (byte cellNumber){
    
    byte deviceAddress;
    byte cellAddress;
    
    switch (cellNumber){
    case 0x01:
    deviceAddress = 0x01;
    CELLAddress = VCELL1;
    中断;
    情况0x02:
    deviceAddress = 0x01;
    CELLAddress = VCELL2;
    中断;
    情况0x03:
    deviceAddress = 0x01;
    CellAddress = VCELL3;
    中断;
    情况0x04:
    deviceAddress = 0x01;
    Cell Address = VCELL4;
    中断;
    情况0x05:
    deviceAddress = 0x01;
    Cell Address = VCELL5;
    中断;
    默认:
    deviceAddress = 0x01;
    Cell Address = VCELL5;
    break;
    }
    
    bqWrite (deviceAddress、ADC_convert、0x01);
    延迟(100);
    字节* CELLRaw = bqRead (deviceAddress、CELLAddress、0x02);
    延迟(10);
    
    int CellVoltage =(CellRaw [0]* 256)+ CELLRaw [1];
    
    // CELL625Voltages[ CELLNumber - 1]= 1);byte
    
    (convertvoltvolt)
    
    
    
    
    
    
    
    (byte)(byte);byteVoltage (byte)、convertInt (byte)+ CONVERT (byte)(bytesktvoltvolt)(byte)(bytesktvolt)(bt)(bytesktvoltvolt)(byte)(bytesktvoltvoltvoltvolt)(byte
    SPI.setDataMode(SPI_MODE1);
    
    //移动器件位并设置位0
    字节逻辑地址= deviceAddress << 1;
    logicalAddress |= 1 << 0;//设置位0、测试 bitSet (x、n)
    
    字节 crcInput[3]={
    logicalAddress、regAddress、regData };
    
    //将 SS 引脚置为低电平以选择芯片
    digitalWrite (slave_select_PIN、low);
    
    //发送和接收 SPI
    spi.transfer (logicalAddress);
    spi.transfer (regAddress);
    spi.transfer (regData);
    spi.transfer (pec (crcInput));
    
    //将 SS 引脚置为高电平以取消选择芯片
    
    
    
    
    
    的 regbyte、SPI.setDataMode(SPI_MODE0);;digitalbyte Address (regbyte);*写入
    SPI.setDataMode(SPI_MODE1);)
    
    //移动器件位并清除位0
    字节逻辑地址= deviceAddress << 1;
    logicalAddress &=~(1 <<0);//清除位0、测试 bitClear (x、n)
    
    //创建用于接收数据的缓冲区并清除静态
    字节接收数据[20];
    memset (sizeData、0、receiveof (
    
    ss)://选择低字节接收数据;//将芯片选为低字节
    digitalWrite (slave_select_PIN、low);
    
    //发送和接收 SPI
    spi.transfer (logicalAddress);
    spi.transfer (regAddress);
    spi.transfer (length);
    for (int i = 0;i < length + 1;i++){
    receivedData[i]= SPI.transfer (0x00);
    }
    
    //将 SS 引脚置为高电平来取消选择芯片:
    digitalWrite (slave_select_PIN、HIGH);
    
    SPI.setDataMode(SPI_MODE0);
    
    //返回从寄存器读取的数据
    返回 receivedData;
    }
    
    double convCellVoltage (字节 hibyte、字节 lobyte){
    //使用给定的转换公式将14位电池电压转换为双
    返回值(((double) hibyte * 256.0)+(double) lobyte)*(6250.0 / 16383.0);
    }
    
    字节 PEC (字节 crcBuffer[]){
    字节 CRC = 0;
    int temp = 0;
    for (int = 0);(int = 0) i < sizeof (crcBuffer)+ 1;i++){
    temp = CRC ^ crcBuffer[i];
    CRC = crcTable[temp];
    }
    返回 CRC;
    } 

    下面显示了输出。 有趣的是、当我验证 ALERT_STATUS 寄存器以验证地址是否分配正确时、它会显示我可以、因为位7是0。 `s、当我通过读取 ADDRESS_CONTROL 寄存器位0..5来读取电路板的地址时、使用掩码我不会获得地址1... 不过、当我更改电压时、可以看到读出的电压随上下变化而变化。 有任何提示?

    ================================================================================

    更改电压时的典型输出

    ================================================================================

    成功写入地址!
    存储地址:47
    V1=2449.18
    V2=2571.26
    V3=2741.41
    V4=2274.08
    V5=2438.12
    ========================================================================================
    V1=2430.11
    V2=2443.46
    V3=2374.41
    V4=2509.84
    V5=2472.07
    ========================================================================================
    V1=2388.15
    V2=2316.04
    V3=2506.41
    V4=2425.15
    V5=2539.98
    ========================================================================================
    V1=2448.42
    V2=2470.55
    V3=2631.92
    V4=2631.92
    V5=2969.92
    ========================================================================================
    V1=3229.72
    V2=3030.58
    V3=3320.90
    V4=3099.25
    V5=2931.77
    ========================================================================================
    V1=3124.81
    V2=3278.93
    V3=3203.40
    V4=3418.18
    V5=323.11.
    ========================================================================================
    V1=3283.13
    V2=3145.79
    V3=3432.67
    V4=3246.12
    V5=3103.45
    ========================================================================================
    V1=3711.16
    V2=3906.11
    V3=3805.77
    v4=4508.10
    V5=3125.19
    ========================================================================================
    V1=3913.36
    V2=3125.19
    V3=3979.73
    v4=4684.73
    V5=3906.49
    ========================================================================================
    V1=3911.07
    V2=3912.97
    V3=3982.79
    V4=3906.49
    V5=3906.49
    ========================================================================================
    V1=3911.45
    V2=3918.31
    V3=3906.49
    V4=3943.11
    V5=3930.90
    ========================================================================================
    V1=4097.23
    V2=4101.43
    V3=3906.49
    v4=4132.33
    V5=4125.85
    ========================================================================================
    V1=4093.80
    V2=3125.19
    V3=4166.67
    v4=4126.23
    V5=4296.37
    ========================================================================================
    V1=4686.26
    V2=4687.40
    V3=4684.73
    V4=4492.46
    V5=4492.46
    ========================================================================================
    V1=3923.27
    V2=3922.89
    V3=3125.19
    V4=3125.19
    V5=3954.94
    ========================================================================================
    V1=3918.70
    V2=3921.75
    V3=3994.23
    V4=4521.45
    V5=4221.60
    ========================================================================================
    V1=3414.36
    V2=3257.19
    V3=3187.37
    V4=3403.68
    V5=3237.73
    ========================================================================================
    V1=3099.25
    V2=2942.07
    V3=3167.15
    V4=2973.74
    V5=3196.53
    ========================================================================================
    V1=2615.90
    V2=2643.36
    V3=2411.04
    V4=1562.60
    V5=2494.20
    ========================================================================================
    V1=2579.27
    V2=2592.24
    V3=2489.24
    V4=2583.09
    V5=2605.98
    ========================================================================================
    V1=2623.53
    V2=2348.09
    V3=2343.51
    V4=2441.56
    V5=2413.32
    ========================================================================================

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    罗杰,我的错…… 更好地看一下我的代码、第135行和第137行可能会互换。 嗯、这意味着、现在没有根据 ALERT_STATUS 寄存器的读数分配地址。 EEPROM 上的任何类型的预编程组3寄存器会导致这种情况吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您必须清除 Alert_STATUS 位。 它不会自行清除。 这意味着 Atert_status [AR]将为1、直到您向该寄存器写入1和0。

    然后它将被清除。 只有正确寻址器件时才会清除。 否则 AR 位将不会清除。

    有道理。 这意味着您必须写入1和0。

    它适用于所有警报和故障寄存器。

    我想  您将具有 POR (故障)和 AR (警报)位。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    组3与寻址和警报 AR 位无关。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我认为您应该监控状态寄存器。
    检查数据表中的说明状态寄存器。


    查看 MSP430的实际代码。
    您不必购买它。
    我之前给您发送了一个链接、您可以查看作为参考。