zoukankan      html  css  js  c++  java
  • W25X16测试程序

    平台:stc12le5a60+W25X16+keil

    W25X16.H

    W25X.H
     1 #ifndef _W25X_H_
     2  #define  _W25X_H_
     3 
     4 #include <REG52.H>
     5 
     6 #define    uint8    unsigned char
     7 #define    uint16    unsigned int
     8 #define    uchar    unsigned char
     9 #define    uint    unsigned int
    10 #define    uint32    unsigned long
    11 
    12 sbit    W25X_HOLD= P1^2;
    13 sbit    W25X_WP    = P1^3;
    14 sbit    W25X_CS    = P1^4;
    15 sbit    W25X_DI    = P1^5;
    16 sbit    W25X_DO    = P1^6;
    17 sbit    W25X_CLK= P1^7;
    18 
    19 #define nop() _nop_()
    20 
    21 #define W25X_WriteEnable        0x06    //写使能  备注:xcc
    22 #define W25X_WriteDisable        0x04     //写禁能
    23 #define W25X_ReadStatusReg        0x05    //读状态寄存器
    24 #define W25X_WriteStatusReg        0x01       //写状态寄存器
    25 #define W25X_ReadData            0x03       //读数据
    26 #define W25X_FastReadData        0x0B      //读数据
    27 #define W25X_FastReadDual        0x3B      //快读双输出
    28 #define W25X_PageProgram        0x02     //页编程
    29 #define W25X_BlockErase            0xD8     //块擦除
    30 #define W25X_SectorErase        0x20     //扇区擦除
    31 #define W25X_ChipErase            0xC7     //芯片擦除
    32 #define W25X_PowerDown            0xB9     //掉电
    33 #define W25X_ReleasePowerDown    0xAB     //释放掉电
    34 #define W25X_DeviceID            0xAB      //器件ID
    35 #define W25X_ManufactDeviceID    0x90      //制造/器件ID
    36 #define W25X_JedecDeviceID        0x9F      //JEDEC ID
    37 
    38 
    39 
    40 uchar    SPI_Read_StatusReg();
    41 void    SPI_Write_StatusReg(byte);
    42 void    SPI_Write_Enable();
    43 void    SPI_Write_Disable();
    44 uchar    SPI_Read_ID1();
    45 uint    SPI_Read_ID2(uchar ID_Addr);
    46 uint    SPI_Read_ID3();
    47 uchar    SPI_Read_Byte(uint32 Dst_Addr); 
    48 void    SPI_Read_nBytes(uint32 Dst_Addr, uchar nBytes_128);
    49 uchar    SPI_FastRead_Byte(uint32 Dst_Addr); 
    50 void    SPI_FastRead_nBytes(uint32 Dst_Addr, uchar nBytes_128);
    51 void    SPI_Write_Byte(uint32 Dst_Addr, uchar byte);
    52 void    SPI_Write_nBytes(uint32 Dst_Addr, uchar nBytes_128);
    53 void    SPI_Erase_Chip();
    54 void    SPI_Erase_Sector(uint32 Dst_Addr);
    55 void    SPI_Wait_Busy();
    56 void    SPI_PowerDown();
    57 void    SPI_ReleasePowerDown();
    58 void    SPI_init();
    59 void    SPI_Send_Byte(uchar out);
    60 uchar    SPI_Get_Byte();
    61 void    delay_nms(uchar i);
    62 void    delay(uchar tt);
    63   
    64 #endif

    W25X.C

    W25X.C
      1 #include <W25X.H>
      2 #include <REG52.H>                                    
      3 #include <intrins.h>
      4 
      5 extern    uint8 upper_128[16];
      6 extern    uint8 tx_buff[16];
      7                                     
      8 void    delay_nms(uchar i)
      9 {    uchar  j;
     10     i=i*2;
     11     for(;i>0;i--)    {   j = 246;    while(--j);    }
     12 }
     13 void    delay(uchar tt)
     14 {    while(tt--);}
     15 //=================================================================================================
     16 //SPI_Read_StatusReg        Reads the status register of the serial flash
     17 //SPI_Write_StatusReg        Performs a write to the status register
     18 //SPI_Write_Enable            Write enables the serial flash
     19 //SPI_Write_Disable            Write disables the serial flash
     20 //SPI_Read_ID1                Reads the device ID using the instruction 0xAB
     21 //SPI_Read_ID2                Reads the manufacturer ID and device ID with 0x90
     22 //SPI_Read_ID3()            Reads the JedecDevice ID
     23 //SPI_Read_Byte                Reads one byte from the serial flash and returns byte(max of 20 MHz CLK frequency)
     24 //SPI_Read_nBytes            Reads multiple bytes(max of 20 MHz CLK frequency)
     25 //SPI_FastRead_Byte            Reads one byte from the serial flash and returns byte(max of 33 MHz CLK frequency)
     26 //SPI_FastRead_nBytes        Reads multiple bytes(max of 33 MHz CLK frequency)
     27 //SPI_Write_Byte            Program one byte to the serial flash
     28 //SPI_Write_nBytes            Program n bytes to the serial flash, n<=256
     29 //SPI_Erase_Chip            Erases entire serial flash
     30 //SPI_Erase_Sector            Erases one sector (64 KB) of the serial flash
     31 //SPI_Wait_Busy                Polls status register until busy bit is low
     32 //=================================================================================================
     33 uchar    SPI_Read_StatusReg()            //读状态寄存器  备注:Xcc
     34 {    uchar byte = 0;
     35     W25X_CS = 0;                            //    enable device
     36     SPI_Send_Byte(W25X_ReadStatusReg);        //    send Read Status Register command
     37     byte = SPI_Get_Byte();                    //    receive byte
     38     W25X_CS = 1;                            //    disable device    
     39     return byte;
     40 }
     41 void    SPI_Write_StatusReg(byte)         //写状态寄存器
     42 {    W25X_CS = 0;                            //    enable device
     43     SPI_Send_Byte(W25X_WriteStatusReg);        //    select write to status register
     44     SPI_Send_Byte(byte);                    //    data that will change the status(only bits 2,3,7 can be written)
     45     W25X_CS = 1;                            //    disable the device
     46 }
     47 void    SPI_Write_Enable()                   //写使能
     48 {    W25X_CS = 0;                            //    enable device
     49     SPI_Send_Byte(W25X_WriteEnable);        //    send W25X_Write_Enable command
     50     W25X_CS = 1;                            //    disable device
     51 }
     52 void    SPI_Write_Disable()                   //写禁能
     53 {    W25X_CS = 0;                            //    enable device
     54     SPI_Send_Byte(W25X_WriteDisable);        //    send W25X_WriteW25X_DIsable command
     55     W25X_CS = 1;                            //    disable device
     56 }
     57 uchar    SPI_Read_ID1()                        //释放掉电/器件ID
     58 {    uchar byte;
     59     W25X_CS = 0;                            //    enable device
     60     SPI_Send_Byte(W25X_DeviceID);            //    send read device ID command (ABh)
     61     SPI_Send_Byte(0);                        //    send address
     62     SPI_Send_Byte(0);                        //    send address
     63     SPI_Send_Byte(0);                        //    send 3_Dummy address
     64     byte = SPI_Get_Byte();                    //    receive Device ID byte    
     65     W25X_CS  = 1;                            //    disable device
     66     delay(4);                                //    remain CS high for tRES2 = 1.8uS
     67     return byte;
     68 }
     69 uint    SPI_Read_ID2(uchar ID_Addr)             //制造/器件ID
     70 {    uint IData16;
     71     W25X_CS = 0;                            //    enable device
     72     SPI_Send_Byte(W25X_ManufactDeviceID);    //    send read ID command (90h)
     73     SPI_Send_Byte(0x00);                    //    send address
     74     SPI_Send_Byte(0x00);                    //    send address
     75     SPI_Send_Byte(ID_Addr);                    //    send W25Pxx selectable ID address 00H or 01H
     76     IData16 = SPI_Get_Byte()<<8;            //    receive Manufature or Device ID byte
     77     IData16 |= SPI_Get_Byte();                //    receive Device or Manufacture ID byte
     78     W25X_CS = 1;                            //    disable device    
     79     return IData16;
     80 }
     81 uint    SPI_Read_ID3()                           //读JEDEC ID
     82 {    uint IData16;
     83     W25X_CS = 0;                            //    enable device
     84     SPI_Send_Byte(W25X_JedecDeviceID);        //    send read ID command (9Fh)
     85     IData16 = SPI_Get_Byte()<<8;            //    receive Manufature or Device ID byte
     86     IData16 |= SPI_Get_Byte();                //    receive Device or Manufacture ID byte
     87     tx_buff[2] = SPI_Get_Byte();    
     88     W25X_CS = 1;                            //    disable device    
     89     return IData16;
     90 }
     91 uchar    SPI_Read_Byte(uint32 Dst_Addr)                //读某地址 数据
     92 {    uchar byte = 0;    
     93     W25X_CS = 0;                                        //    enable device
     94     SPI_Send_Byte(W25X_ReadData);                        //    read command
     95     SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));//    send 3 address bytes
     96     SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8));
     97     SPI_Send_Byte((uchar)(Dst_Addr & 0xFF));
     98     byte = SPI_Get_Byte();
     99     W25X_CS = 1;                                        //    disable device    
    100     return byte;                                        //    return one byte read
    101 }
    102 void    SPI_Read_nBytes(uint32 Dst_Addr, uchar nBytes_128)    //读某地址起nBytes_128字节以内内容
    103 {    uint32 i = 0;    
    104     W25X_CS = 0;                                        //    enable device
    105     SPI_Send_Byte(W25X_ReadData);                        //    read command
    106     SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16));        //    send 3 address bytes
    107     SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
    108     SPI_Send_Byte(Dst_Addr & 0xFF);
    109     for (i = 0; i < nBytes_128; i++)                    //    read until no_bytes is reached
    110         upper_128[i] = SPI_Get_Byte();                    //    receive byte and store at address 80H - FFH
    111     W25X_CS = 1;                                        //    disable device
    112 }
    113 uchar    SPI_FastRead_Byte(uint32 Dst_Addr)                  //快读 某地址 数据
    114 {    uchar byte = 0;
    115     W25X_CS = 0;                                        //    enable device
    116     SPI_Send_Byte(W25X_FastReadData);                    //    fast read command
    117     SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16));        //    send 3 address bytes
    118     SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
    119     SPI_Send_Byte(Dst_Addr & 0xFF);
    120     SPI_Send_Byte(0xFF);                                //    dummy byte
    121     byte = SPI_Get_Byte();
    122     W25X_CS = 1;                                        //    disable device    
    123     return byte;                                        //    return one byte read
    124 }
    125 void    SPI_FastRead_nBytes(uint32 Dst_Addr, uchar nBytes_128)      //快读 某地址 nBytes_128 个字节数据
    126 {    uchar i = 0;    
    127     W25X_CS = 0;                                        //    enable device
    128     SPI_Send_Byte(W25X_FastReadData);                    //    read command
    129     SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16));        //    send 3 address bytes
    130     SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
    131     SPI_Send_Byte(Dst_Addr & 0xFF);
    132     SPI_Send_Byte(0xFF);                                //    dummy byte
    133     for (i = 0; i < nBytes_128; i++)                    //    read until no_bytes is reached
    134         upper_128[i] = SPI_Get_Byte();                    //    receive byte and store at address 80H - FFH
    135     W25X_CS = 1;                                        //    disable device
    136 }
    137 void    SPI_Write_Byte(uint32 Dst_Addr, uchar byte)          //页编程
    138 {    W25X_CS = 0;                                    //    enable device
    139     SPI_Write_Enable();                                //    set WEL
    140     SPI_Wait_Busy();    
    141     W25X_CS = 0;    
    142     SPI_Send_Byte(W25X_PageProgram);                //    send Byte Program command
    143     SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16));    //    send 3 address bytes
    144     SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
    145     SPI_Send_Byte(Dst_Addr & 0xFF);
    146     SPI_Send_Byte(byte);                            //    send byte to be programmed
    147     W25X_CS = 1;                                    //    disable device
    148 }
    149 void    SPI_Write_nBytes(uint32 Dst_Addr, uchar nBytes_128)         //页编程 128个字节
    150 {    
    151     uchar i, byte;    
    152     W25X_CS = 0;                    /* enable device */
    153     SPI_Write_Enable();                /* set WEL */
    154     W25X_CS = 0;
    155     SPI_Send_Byte(W25X_PageProgram);         /* send Byte Program command */
    156     SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16));    /* send 3 address bytes */
    157     SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
    158     SPI_Send_Byte(Dst_Addr & 0xFF);
    159     
    160     for (i = 0; i < nBytes_128; i++)
    161     {
    162         byte = upper_128[i];
    163         SPI_Send_Byte(byte);        /* send byte to be programmed */
    164     }    
    165     W25X_CS = 1;                /* disable device */
    166 }
    167 void    SPI_Erase_Chip()                     //擦除芯片
    168 {
    169     W25X_CS = 0;                                        //    enable device
    170     SPI_Write_Enable();                                    //    set WEL
    171     W25X_CS = 0;
    172     SPI_Wait_Busy();
    173     W25X_CS = 0;
    174     SPI_Send_Byte(W25X_ChipErase);                        //    send Chip Erase command
    175     W25X_CS = 1;                                        //    disable device
    176 }
    177 void    SPI_Erase_Sector(uint32 Dst_Addr)                //扇区擦除
    178 {    W25X_CS = 0;                                        //    enable device
    179     SPI_Write_Enable();                                    //    set WEL
    180     W25X_CS = 0;
    181     SPI_Send_Byte(W25X_SectorErase);                    //    send Sector Erase command
    182     SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));//    send 3 address bytes
    183     SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8));
    184     SPI_Send_Byte((uchar)Dst_Addr & 0xFF);
    185     W25X_CS = 1;                                        //    disable device
    186 }
    187 void    SPI_Wait_Busy()                                 //等待忙结束
    188 {    while (SPI_Read_StatusReg() == 0x03)
    189         SPI_Read_StatusReg();                //    waste time until not busy WEL & Busy bit all be 1 (0x03)
    190 }
    191 void    SPI_PowerDown()
    192 {    W25X_CS = 0;                            //    enable device
    193     SPI_Send_Byte(W25X_PowerDown);            //    send W25X_PowerDown command 0xB9
    194     W25X_CS = 1;                            //    disable device
    195     delay(6);                                //    remain CS high for tPD = 3uS
    196 }
    197 void    SPI_ReleasePowerDown()
    198 {    W25X_CS = 0;                            //    enable device
    199     SPI_Send_Byte(W25X_ReleasePowerDown);    //    send W25X_PowerDown command 0xAB
    200     W25X_CS = 1;                            //    disable device
    201     delay(6);                                //    remain CS high for tRES1 = 3uS
    202 }
    203 
    204 
    205 
    206 #ifdef    SST_SPI
    207 void    SPI_init()
    208 {    P1 = 0xFF;
    209     SPCR = 0x50;
    210 }
    211 void    SPI_Send_Byte(uchar out)
    212 {    unsigned char temp;
    213     SPDR = out;
    214     do    {    temp = SPSR & 0x80;    }    while (temp != 0x80);
    215     SPSR = SPSR & 0x7F;
    216 }
    217 uchar    SPI_Get_Byte()
    218 {    unsigned char temp;
    219     SPDR = 0x00;
    220     do    {    temp = SPSR & 0x80;    }    while (temp != 0x80);
    221     SPSR = SPSR & 0x7F;
    222     return SPDR;
    223 }
    224 #endif
    225 
    226 #ifndef    SST_SPI
    227 void    SPI_init()
    228 {    W25X_CLK = 0;                            //    set clock to low initial state for SPI operation mode 0
    229 //    W25X_CLK = 1;                            //    set clock to High initial state for SPI operation mode 3
    230 //    _hold = 1;
    231     W25X_WP = 1;
    232     W25X_CS = 1;    
    233     SPI_Write_Disable();    
    234 }
    235 void    SPI_Send_Byte(uchar out)
    236 {    uchar i = 0;    
    237     for (i = 0; i < 8; i++)
    238     {    if ((out & 0x80) == 0x80)            //    check if MSB is high
    239             W25X_DI = 1;
    240         else
    241             W25X_DI = 0;                    //    if not, set to low
    242         W25X_CLK = 1;                        //    toggle clock high
    243         out = (out << 1);                    //    shift 1 place for next bit
    244         nop();nop();nop();nop();
    245         W25X_CLK = 0;                        //    toggle clock low
    246     }
    247 }
    248 uchar    SPI_Get_Byte()
    249 {    uchar i = 0, in = 0, temp = 0;    
    250     for (i = 0; i < 8; i++)
    251     {    in = (in << 1);                        //    shift 1 place to the left or shift in 0
    252         temp = W25X_DO;                        //    save input
    253         W25X_CLK = 1;                        //    toggle clock high
    254         if (temp == 1)                        //    check to see if bit is high
    255             in |= 0x01;                        //    if high, make bit high
    256         W25X_CLK = 0;                        //    toggle clock low
    257     }    
    258     return in;
    259 }
    260 #endif

    MAIN.C

    MAIN.C
    #include <REG52.H>
    #include <intrins.h>
    #include <W25X.H>
        
    
    
    
    #define    uint8    unsigned char
    #define    uint16    unsigned int
    #define    uchar    unsigned char
    #define    uint    unsigned int
    #define    uint32    unsigned long
    
    
    void    init_cpu(void);
    void    delay(uchar tt);
    void    trace(uchar *str,uchar len);
    void    test_page(uchar addr);
    void    read_page(uchar addr);
    void    Verify(uchar byte, uchar cor_byte);
    
    uint8    Rxtemp;
    bit        MYTI;
    uint8    tx_buff[16];
    uint8    upper_128[16];
    bit        rx_ok;
    
    void main(void)
    {    uint i;
        W25X_HOLD= 1;
        init_cpu();    
        SPI_init();
    
        tx_buff[0]='O';
        tx_buff[1]='K';
        trace(tx_buff,2);
    
        for(;;)
        {    if(rx_ok == 1)
            {    rx_ok = 0;
                switch(Rxtemp)
                {    case 0x01:
                        Rxtemp = 0;
                        tx_buff[0] = SPI_Read_ID1();
                        trace(tx_buff,1);
                        break;
                    case 0x02:
                        i = SPI_Read_ID2(0x00);
                        tx_buff[1] = (uchar)i;
                        tx_buff[0] = (uchar)(i>>8);
                        trace(tx_buff,2);
                        break;
                    case 0x03:
                        i = SPI_Read_ID3();
                        tx_buff[1] = (uchar)i;
                        tx_buff[0] = (uchar)(i>>8);
                        trace(tx_buff,3);
                        break;
                    case 0x04:
                        tx_buff[0] = SPI_Read_Byte(0x00000000);
                        trace(tx_buff,1);
                        break;
                    case 0x05:
                        tx_buff[0] = 0x55;
                        SPI_Write_Byte(0x00000000,0xa5);          
                        trace(tx_buff,1);
                        break;
                    case 0x06:
                        tx_buff[0] = SPI_Read_StatusReg();
                        trace(tx_buff,1);
                        break;
                    case 0x07:
                        SPI_Write_Enable();    
                        break;
                    case 0x08:
                        upper_128[0]=0x01;upper_128[1]=0x02;upper_128[2]=0x03;upper_128[3]=0x04;
                        SPI_Write_nBytes(0x00000000,4);
                        break;
                    case 0x09:
                        SPI_Erase_Chip();
                        break;
                    case 0x0a:
                        SPI_Erase_Sector(0x000ff000);
                        while(1)
                        {    tx_buff[0] = SPI_Read_StatusReg();
                            if(tx_buff[0] == 0)
                            {    trace(tx_buff,1);
                                break;
                            }
                        }
                        break;
                    case 0x0b:
                        test_page(0x00);
                        break;
                    case 0x0c:
                        read_page(0x00);
                        break;
                    default:
                        break;
                }            
            }            
        }
    }
    
    void init_cpu(void)
    {    TMOD = 0x21;            
        PCON = PCON | 0x80;        //波特率加倍
        SCON  = 0x50;            //异步、10位、波特率可变,无校验位
        TH1   = 0xf4;            //在11.0592M晶振下,波特率是9600,
        TL1   = 0xf4;            
        TR1   = 1;              //T1 timer run
        ES    = 1;                //uart interrupt enable    
        EA = 1;                    //all interrupt enable
    }
    
    //串口中断程序
    void UART_isr(void) interrupt 4
    { 
        if(RI)
        {
            RI = 0;
            Rxtemp = SBUF;   //接收
            //SBUF = Rxtemp;      //发送
            rx_ok = 1;
            return;
        }
        if(TI)
        {
            TI = 0;
            MYTI = 1;        
         }
    }
    void test_page(uchar addr)
    {    uint i; uchar byte;
        uint32 Dst_Addr;    
        W25X_CS = 0;                                            //    enable device
        SPI_Write_Enable();                                        //    set WEL
        W25X_CS = 0;
        Dst_Addr = (uint32)addr*256;
        Dst_Addr = 0x0ff000;//(uint32)addr*256;
        SPI_Send_Byte(W25X_PageProgram);                        //    send Byte Program command
        SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));    //    send 3 address bytes
        SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8));
        SPI_Send_Byte((uchar)(Dst_Addr & 0xFF));
        
        for (i = 0; i < 256; i++)                                //    send byte to be programmed
            SPI_Send_Byte(i);
        W25X_CS = 1;    
        
        delay_nms(5);
        
        W25X_CS = 0;
        while(1)
        {    tx_buff[0] = SPI_Read_StatusReg();
            trace(tx_buff,1);
            if(tx_buff[0] == 0)    break;
        }
        Dst_Addr = 0x0ff000;
        for (i = 0; i < 256; i++)
        {    byte = SPI_Read_Byte(Dst_Addr+i);
            ES = 0;
            SBUF = byte;
            while (TI == 0);
            TI = 0;
            ES = 1;
        }
        W25X_CS = 1;
    }
    //=================================================================================================
    void read_page(uchar addr)
    {    uint i;
        uchar byte;
        uint32 Dst_Addr;
        Dst_Addr = addr*256;
        Dst_Addr = 0x0ff000;
        W25X_CS = 0;
        for (i = 0; i < 256; i++)
        {    byte = SPI_Read_Byte(Dst_Addr+i);
            ES = 0;
            SBUF = byte;
            while (TI == 0);
            TI = 0;
            ES = 1;
        }
        W25X_CS = 1;
    }
    //=================================================================================================
    void Verify(uchar byte, uchar cor_byte)
    {    if (byte != cor_byte)
        {    while(1);
                //LED_Error = 0; /* display to view error on LED. */            
        }
    }
    //=================================================================================================
    void myputchar(uchar c)
    {    
        ES = 0;
        SBUF = c;
        while (TI == 0);
        TI = 0;
        ES = 1;
    }
    //=================================================================================================
    void trace(uchar *str,uchar len)
    {    uint i;
        for(i=0;i<len;i++)    {    myputchar(*str);    str++;    }
    }

     以上测试正确

  • 相关阅读:
    每日一篇文献:Robotic pick-and-place of novel objects in clutter with multi-affordance grasping and cross-domain image matching
    每日一篇文献:Intuitive Bare-Hand Teleoperation of a Robotic Manipulator Using Virtual Reality and Leap Motion
    每日一篇文献:Virtual Kinesthetic Teaching for Bimanual Telemanipulation
    HEBI Robotic Arm VR Teleoperation
    「iQuotient Case」AR device teleoperated robotic arm
    VR and Digital Twin Based Teleoperation of Robotic Arm
    HEBI Robotic Arm VR Teleoperation
    Human Robot Interaction
    Immersive Teleoperation Project
    机器人演示学习
  • 原文地址:https://www.cnblogs.com/scdyxcc/p/2870470.html
Copyright © 2011-2022 走看看