发新帖本帖赏金 50.00元(功能说明)我要提问
返回列表

[单片机芯片] 基于CH32V103驱动RFID射频阅读器

[复制链接]
4847|3
手机看帖
扫描二维码
随时随地手机跟帖
yangjiaxu|  楼主 | 2022-3-31 14:08 | 显示全部楼层 |阅读模式
本帖最后由 yangjiaxu 于 2022-3-31 14:10 编辑
首先感谢21ic和小管家举办的这个[活动] 【第1期】你选开发板,二姨家买单;很荣幸因为脸熟(其实是混子)得到了这次活动的中奖名额,说实话这板子到手挺长时间了,这么晚才发属实是我个人原因,还有就是疫情肆虐,真的让我板子与人相隔两地。哈哈哈,好了闲话少说,还是开启这次主题任务吧。
本次豆包选择的开发板是沁恒的开发板“CH32V103R8”为什么选择这款开发板呢,其实原因有三。第一,因为没怎么接触过沁恒RISC-V内核的开发板,工作中一直都在使用Arm内核的单片机在玩耍,可能接触和体验新鲜事物是做工程师的一种本能吧,所以让我选择了沁恒。第二,因为朋友推荐我玩沁恒的MCU是因为沁恒的MCU较容易好上手,而且这个32位单片机在国产32位的MCU中是比较能打的(主要是有性价比)。第三,主要是我缺了个link调试器,我是一个对调试工具比较有感觉的一个野生工程师,手里的调试器也算是多种多样,所以一看沁恒这个买开发板送调试器的活动,我岂有不buy的道理。因此,众多理由让我选择了沁恒这款开发板。到手之后,果然没让我失望。接下来就来赏析这款开发板的样子吧。
01.jpg
开发板包装

02.jpg
开发板和调试器

其实这次购买还赠送了2片MCU,在这个芯片紧缺,在朋友圈盛行的一句 “芯片和白菜一个价的时代”,送我两片芯片无疑是地主行为。
03.jpg

接下来就是搭环境了,其实Risc-V的环境怎么搭我是真不是很清楚,但是沁恒这个CH32V103这个搭建环境是真的很容易,首先下载个开发环境,下载MounRiver_Studio_Setup_V170.zip即可,下载链接接下来就是安装,然后找沁恒关于CH32V103的资料例程即可,资料链接。通过官网也可以看到CH32V103的开发资源和外设情况。
04.png

产品特点
  • 青稞V3A处理器,最高80MHz系统主频;
  • 支持单周期乘法和硬件除法;
  • 20KB SRAM,64KB CodeFlash;
  • 供电范围:2.7V ~ 5.5V,GPIO同步供电电压;
  • 多种低功耗模式:睡眠/停止/待机;
  • 上电/断电复位(POR/PDR);
  • 可编程电压监测器(PVD);
  • 7通道DMA控制器;
  • 16路TouchKey通道监测;
  • 16路12位ADC转换通道;
  • 7个定时器;
  • 1个USB2.0主机/设备接口(全速和低速);
  • 2个IIC接口(支持SMBus/PMBus);
  • 3个USART接口;
  • 2个SPI接口(支持Master和Slave模式);
  • 51个I/O口,所有的I/O口都可以映射到16个外部中断;
  • CRC计算单元,96位芯片唯一ID;
  • 串行单线调试(SWD)接口;
  • 封装形式:LQFP64M、LQFP48、QFN48。
介绍完硬件,其实就可以写代码来玩玩这款得意的MCU了。
打开一个官方例程,我选择的是GPIO的例程,然后改了个名字,因为我想用这个MCU驱动一下FM17522射频阅读器,所以索性改了工程名字。先看看代码风格之类的,emmm,真香,这不是很熟悉的库函数形式么。

05.png

接下来添加FM17522的驱动代码,然后就是移植程序了。
移植过程.jpg
以前换一款MCU来说,移植程序是非常费劲儿的,不过使用沁恒这款MCU的话就不用担心这个问题,基本上一看就会,一用就OK,所以我移植这个工程代码也是非常容易的。因为还需要修改一些变量和参数之类的。所以,大概用了20分钟吧。
分享一下基础代码:
/**********************************以下为用户程序************************************/
void FM17522_IOinit(void)
{
    u8 loop = 0;

    GPIO_InitTypeDef GPIO_InitStructure;
//    GPIO_InitTypeDef GPIO_InitStructure = {0};
    //不要忘记开启AFIO时钟(JTAG复用时RCC_APB2Periph_AFIO)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    FM17522_Reset();
    no_fm_flag = 1;

    while(loop++ < 6)
    {
        if(FM17522_TEST())  // 测试读卡芯片FM17522是否在位
        {
            no_fm_flag = 0;
            break;
        }
    }
}
/*********************************************************************************************************
** 函数名称:FM17522_TEST
** 函数描述:MCU与读卡芯片通信测试函数
** 输入参数:无
** 返回值  :TRUE---测试通过    FALSE----测试失败
** 说明:不同的读卡芯片的选取用于测试的寄存器不一样,需要更具具体芯片而确定目标寄存器
*********************************************************************************************************/
u8 FM17522_TEST(void)
{
    volatile u8 ucRegVal;

    FM17522_Reset();                                   // 硬件复位
    ucRegVal = FM17522_Read_Reg(ControlReg);
    FM17522_Write_Reg(ControlReg, 0x10);               // 启动读写器模式
    ucRegVal = FM17522_Read_Reg(ControlReg);
    FM17522_Write_Reg(GsNReg, 0xF0 | 0x04);            // CWGsN = 0xF; ModGsN = 0x4
    ucRegVal = FM17522_Read_Reg(GsNReg);

    if(ucRegVal != 0xF4)                               // 验证接口正确
        return FALSE;

    return TRUE;
}
void FM17522_Reset(void)
{
    SPI_SCK_SET;
    Delay_Us(300); // 延时300us
    SPI_RST_CLR;
    Delay_Us(500); // 延时500us
    SPI_RST_SET;
    Delay_Us(1000); // 延时1000us
}
/********************************************
函数名:            Clear_BitMask
功能:            清除位寄存器操作

输入参数:        reg_add,寄存器地址;mask,寄存器清除位
********************************************/
void Clear_BitMask(u8 reg_add, u8 mask)
{
    FM17522_Write_Reg(reg_add, FM17522_Read_Reg(reg_add) & ~mask); // clear bit mask
}
/*************************************************************/
/*函数名:            Set_BitMask                                                                         */
/*功能:            置位寄存器操作                                                                 */
/*输入参数:        reg_add,寄存器地址;mask,寄存器置位                 */
/*返回值:            TRUE                                                                                         */
/*                                FALSE                                                                                 */
/*************************************************************/
void Set_BitMask(u8 reg_add, u8 mask)
{
    FM17522_Write_Reg(reg_add, FM17522_Read_Reg(reg_add) | mask); // set bit mask
}
/**********************************************/
/** 函数名:            Set_RF                     **/
/** 功能:            设置射频输出                 **/
/** 输入参数:        mode,射频输出模式           **/
/**                                0,关闭输出                        **/
/**       1,仅打开TX1输出                   **/
/**       2,仅打开TX2输出                   **/
/**                                3,TX1,TX2打开输出,TX2为反向输出 **/
/**********************************************/
void Set_Rf(u8 mode)
{
    if((FM17522_Read_Reg(TxControlReg) & 0x03) == mode)
        return;

    if (mode == 0)
    {
        Clear_BitMask(TxControlReg, 0x03); //关闭TX1,TX2输出
    }
    else if (mode == 1)
    {
        Clear_BitMask(TxControlReg, 0x01); //仅打开TX1输出
    }
    else if (mode == 2)
    {
        Clear_BitMask(TxControlReg, 0x02); //仅打开TX2输出
    }
    else if (mode == 3)
    {
        Set_BitMask(TxControlReg, 0x03); //打开TX1,TX2输出
    }

    Delay_Ms(100);
}
void Fm17522_ConfigISOType(u8 type)
{
    if (type == 0)                     //ISO14443_A
    {
        Set_BitMask(ControlReg, 0x10); //ControlReg 0x0C 设置reader模式
        Set_BitMask(TxAutoReg, 0x40);  //TxASKReg 0x15 设置100%ASK有效
        FM17522_Write_Reg(TxModeReg, 0x00);    //TxModeReg 0x12 设置TX CRC无效,TX FRAMING =TYPE A
        FM17522_Write_Reg(RxModeReg, 0x00);    //RxModeReg 0x13 设置RX CRC无效,RX FRAMING =TYPE A
        FM17522_Write_Reg(RFCfgReg, 0x48);     //增益调节至48DB 2021.01.16
    }
    else if (type == 1)                        //ISO14443_B
    {
        FM17522_Write_Reg(ControlReg, 0x10);
        FM17522_Write_Reg(TxModeReg, 0x83); //BIT1~0 = 2'b11:ISO/IEC 14443B
        FM17522_Write_Reg(RxModeReg, 0x83); //BIT1~0 = 2'b11:ISO/IEC 14443B
        FM17522_Write_Reg(TxAutoReg, 0x00);
        FM17522_Write_Reg(RxThresholdReg, 0x55);
        FM17522_Write_Reg(RFCfgReg, 0x48); //?????????????
        FM17522_Write_Reg(TxBitPhaseReg, 0x87); //默认值
        FM17522_Write_Reg(GsNReg, 0x83);
        FM17522_Write_Reg(CWGsPReg, 0x10);
        FM17522_Write_Reg(GsNOffReg, 0x38);
        FM17522_Write_Reg(ModGsPReg, 0x10);
    }

    Delay_Us(1000);
}
/********************************************
函数名:           Fm17522_SetTimer
功能:            设置接收延时
输入参数:        delaytime,延时时间(单位为毫秒)
返回值:            TRUE
********************************************/
u8 Fm17522_SetTimer(unsigned long delaytime)//设定超时时间(ms)
{
    unsigned long TimeReload;
    unsigned int Prescaler;

    Prescaler = 0;
    TimeReload = 0;

    while(Prescaler < 0xfff)
    {
        TimeReload = ((delaytime * (long)13560) - 1) / (Prescaler * 2 + 1);

        if( TimeReload < 0xffff)
            break;

        Prescaler++;
    }

    TimeReload = TimeReload & 0xFFFF;
    Set_BitMask(TModeReg, Prescaler >> 8);
    FM17522_Write_Reg(TPrescalerReg, Prescaler & 0xFF);
    FM17522_Write_Reg(TReloadMSBReg, TimeReload >> 8);
    FM17522_Write_Reg(TReloadLSBReg, TimeReload & 0xFF);
    return TRUE;
}
/*************************************************************
函数名:            Clear_FIFO
功能:              清空FIFO

输入参数:          无
输出参数:
返回值:            TRUE
                                      FALSE
************************************************************/
u8 Clear_FIFO(void)
{
    Set_BitMask(FIFOLevelReg, 0x80); //清除FIFO缓冲

    if (FM17522_Read_Reg(FIFOLevelReg) == 0)
        return TRUE;
    else
        return FALSE;
}
//ATQA是只有两个字节,UID却是4个字节加一个BCC校验值所以针对7字节UID防碰撞时就需要最多15字节的UID来存放
//SAK是一个字节的SAK+CRC_A(2字节)
/****************************************************************************************/
/*名称:TypeA_Request                                                                                                                                        */
/*功能:TypeA_Request卡片寻卡                                                                                                                        */
/*输入:                                                                                                                                                                */
/*                                                                                                                                                                */
/*                                                                                                                                                                                */
/*输出:                                                                                                                                                                 */
/*                       pTagType[0],pTagType[1] =ATQA                                                         */
/*               TRUE: 应答正确                                                                      */
/*                         FALSE: 应答错误                                                                                                                                */
/****************************************************************************************/
u8 Fm17522_TypeA_Request(void)
{
    unsigned char  result, send_buff[1], rece_buff[2];
    unsigned int  rece_bitlen;
        
    Clear_BitMask(TxModeReg, 0x80); //关闭TX CRC
    Clear_BitMask(RxModeReg, 0x80); //关闭RX CRC
    Set_BitMask(RxModeReg, 0x08);//关闭位接收
    Clear_BitMask(Status2Reg, 0x08);
    FM17522_Write_Reg(BitFramingReg, 0x07);
    send_buff[0] = 0x26;
    Fm17522_SetTimer(1);
    Clear_FIFO();
    result = Fm17522_Comm(Transceive, send_buff, 1, rece_buff, &rece_bitlen);

    if ((result == TRUE) && (rece_bitlen == 2 * 8))
    {
        memcpy(atqa, rece_buff, 2);
    }

    return result;
}
/*********************************************
函数名:          Fm17522_Comm (不利用IRQ管脚的情况)
功能:            读卡器通信

输入参数:        Command,通信操作命令;
                                                pInData,发送数据数组;
                                                InLenByte,发送数据数组字节长度;
                                                pOutData,接收数据数组;
                                                pOutLenBit,接收数据的位长度
返回值:            TRUE
                                FALSE
********************************************/
u8 Fm17522_Comm(u8 Command, u8 *pInData, u8 InLenByte, u8 *pOutData, uint *pOutLenBit)
{
    uint8_t status  = FALSE;
    uint8_t irqEn   = 0x00;
    uint8_t waitFor = 0x00;
    uint8_t lastBits;
    uint8_t n;
    uint32_t i;
    FM17522_Write_Reg(ComIrqReg, 0x7F);               //清楚IRQ标记
    FM17522_Write_Reg(TModeReg, 0x80);                //设置TIMER自动启动

    switch (Command)
    {
        case MFAuthent:                                                  /* Mifare认证                   */
            irqEn   = 0x12;
            waitFor = 0x10;
            break;

        case Transceive:                                               /* 发送FIFO中的数据到天线,传输后激活接收电路*/
            irqEn   = 0x77;
            waitFor = 0x30;
            break;

        default:
            break;
    }

    FM17522_Write_Reg(ComIEnReg, irqEn | 0x80);
    FM17522_Write_Reg(CommandReg, Idle);
    Set_BitMask(FIFOLevelReg, 0x80);

    for (i = 0; i < InLenByte; i++)
    {
        FM17522_Write_Reg(FIFODataReg, pInData[i]);
    }

    FM17522_Write_Reg(CommandReg, Command);

    if (Command == Transceive)
    {
        Set_BitMask(BitFramingReg, 0x80);
    }

    i = 20000;                                                            /* 根据时钟频率调整,操作M1卡最大等待时间25ms*/

    do
    {
        n = FM17522_Read_Reg(ComIrqReg);
        i--;
    }
    while ((i != 0) && !(n & 0x01) && !(n & waitFor));           //i==0表示延时到了,n&0x01!=1表示PCDsettimer时间未到

    Clear_BitMask(BitFramingReg, 0x80);

    if (i != 0)
    {
        if(!(FM17522_Read_Reg(ErrorReg) & 0x1B))
        {
            status = TRUE;

            if (n & irqEn & 0x01)
            {
                status = 0xEE;
            }

            if (Command == Transceive)
            {
                n = FM17522_Read_Reg(FIFOLevelReg);
                lastBits = FM17522_Read_Reg(ControlReg) & 0x07;

                if (lastBits)
                {
                    *pOutLenBit = (n - 1) * 8 + lastBits;
                }
                else
                {
                    *pOutLenBit = n * 8;
                }

                if (n == 0)
                {
                    n = 1;
                }

                if (n > 64)
                {
                    n = 64;
                }

                for (i = 0; i < n; i++)
                {
                    pOutData[i] = FM17522_Read_Reg(FIFODataReg);
                }
            }
        }
        else
        {
            status = FALSE;
        }
    }

    Clear_BitMask(BitFramingReg, 0x80); //关闭发送
    return status;
}
/****************************************************************************************/
/*名称:Fm17522_TypeA_Anticollision                                                                                                                                */
/*功能:卡片防冲突                                                                                                        */
/*输入:selcode =0x93,0x95,0x97                                                                                                                */
/*                                                                                                                                                                */
/*                                                                                                                                                                                */
/*输出:                                                                                                                                                                 */
/*      TRUE: 应答正确                                                                      */
/*                 FALSE: 应答错误                                                                                                                                */
/****************************************************************************************/
u8 Fm17522_TypeA_Anticollision(unsigned char selcode)
{
    unsigned char   result, i, send_buff[2], rece_buff[5];
    unsigned int   rece_bitlen;
    Clear_BitMask(TxModeReg, 0x80);
    Clear_BitMask(RxModeReg, 0x80);
    Clear_BitMask(Status2Reg, 0x08);
    FM17522_Write_Reg(BitFramingReg, 0x00);
    Clear_BitMask(CollReg, 0x80);

    send_buff[0] = selcode;
    send_buff[1] = 0x20;             //NVB
    Fm17522_SetTimer(1);
    Clear_FIFO();
    result = Fm17522_Comm(Transceive, send_buff, 2, rece_buff, &rece_bitlen);
    i = ((selcode - 0x93) / 2) * 5;

    if (result == TRUE)
    {
//        memcpy(uid[i], rece_buff, 5);
        for (i = 0; i < 5; ++i) {
            uid[i] = rece_buff[i];
        }

        if (uid[4 + i] != (uid[i]^uid[1 + i]^uid[2 + i]^uid[3 + i])) //UID0、UID1、UID2、UID3、BCC(校验字节)
            result = FALSE;
    }

    return result;
}
/****************************************************************************************/
/*名称:TypeA_Select                                                                                                                                        */
/*功能:TypeA_Select卡片选卡                                                                                                                        */
/*输入:selcode =0x93,0x95,0x97                                                                                                                */
/*      pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID                                                                  */
/*                                                                                                                                                                                */
/*输出:                                                                                                                                                                 */
/*                       pSak[0],pSak[1],pSak[2] =SAK                                                                    */
/*               TRUE: 应答正确                                                                      */
/*                         FALSE: 应答错误                                                                                                                                */
/****************************************************************************************/
u8 Fm17522_TypeA_Select(unsigned char selcode)
{
    unsigned char   result, i, send_buff[7], rece_buff[5];
    unsigned int   rece_bitlen;
    FM17522_Write_Reg(BitFramingReg, 0x00);
    Set_BitMask(TxModeReg, 0x80);     //打开TX CRC
    Set_BitMask(RxModeReg, 0x80);       //打开接收RX 的CRC校验
    Clear_BitMask(Status2Reg, 0x08);

    send_buff[0] = selcode;        //SEL
    send_buff[1] = 0x70;         //NVB

    i = ((selcode - 0x93) / 2) * 5;
//    memcpy(&send_buff[2],uid[i], 5);
    for (i = 0; i < 5; ++i) {
        send_buff[i + 2] = uid[i];
    }
    Fm17522_SetTimer(1);
    Clear_FIFO();
    result = Fm17522_Comm(Transceive, send_buff, 7, rece_buff, &rece_bitlen);

    i = (selcode - 0x93) / 2;

    if (result == TRUE)
    {
       sak[i] = rece_buff[0];
    }
    return result;
}
/****************************************************************************************/
/*名称:Fm17522_TypeA_CardActive                                                                        */
/*功能:TypeA_CardActive卡片激活                                        */
/*输入:                                                                                                                                        */
/*输出:        pTagType[0],pTagType[1] =ATQA         */
/*              pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID         */
/*              pSak[0],pSak[1],pSak[2] =SAK                                    */
/****************************************************************************************/
u8 Fm17522_TypeA_CardActive(void)
{
    u8 result, i;
    Set_Rf(3);   //turn on radio
    Fm17522_ConfigISOType(0);

    for(i = 0; i < 2; i++)
    {
        result = Fm17522_TypeA_Request(); //寻卡 Standard         send request command Standard mode

        if(result == 1)  break;
    }

    if(i == 2)
        return FALSE;

    if((atqa[0] & 0xC0) == 0x00)    //M1卡,ID号只有4位
    {
        result = Fm17522_TypeA_Anticollision(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }
    }
    else if((atqa[0] & 0xC0) == 0x40) //ID号有7位
    {
        result = Fm17522_TypeA_Anticollision(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Anticollision(0x95);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x95);

        if (result == FALSE)
        {
            return FALSE;
        }
    }
    else if((atqa[0] & 0xC0) == 0x80)   //ID号有10位
    {
        result = Fm17522_TypeA_Anticollision(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x93);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Anticollision(0x95);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x95);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Anticollision(0x97);

        if (result == FALSE)
        {
            return FALSE;
        }

        result = Fm17522_TypeA_Select(0x97);

        if (result == FALSE)
        {
            return FALSE;
        }
    }

    return result;
}

/*****************************************************************************************/
/*名称:Fm17522_Mifare_Auth                                                                                                                                                 */
/*功能:Mifare_Auth卡片认证                                                                                                                                 */
/*输入:mode,认证模式(0:key A认证,1:key B认证);sector,认证的扇区号(0~15)                 */
/*                *mifare_key,6字节认证密钥数组;*card_uid,4字节卡片UID数组                                                 */
/*输出:                                                                                                                                                                         */
/*                TRUE    :认证成功                                                                                                                                         */
/*                FALSE :认证失败                                                                                                                                           */
/*****************************************************************************************/
u8 Fm17522_Mifare_Auth(u8 mode, u8 sector, u8 *mifare_key, u8 *card_uid)
{
    unsigned char  send_buff[12], rece_buff[1], result;
    unsigned int  rece_bitlen;

    if(mode == 0x0)
        send_buff[0] = 0x60; //keyA认证

    if(mode == 0x1)
        send_buff[0] = 0x61; //keyB认证

    send_buff[1] = sector * 4 + 3;
    send_buff[2] = mifare_key[0];
    send_buff[3] = mifare_key[1];
    send_buff[4] = mifare_key[2];
    send_buff[5] = mifare_key[3];
    send_buff[6] = mifare_key[4];
    send_buff[7] = mifare_key[5];
    send_buff[8] = card_uid[0];
    send_buff[9] = card_uid[1];
    send_buff[10] = card_uid[2];
    send_buff[11] = card_uid[3];

    Fm17522_SetTimer(1);
    Clear_FIFO();
    result = Fm17522_Comm(MFAuthent, send_buff, 12, rece_buff, &rece_bitlen); //Authent认证

    if (result == TRUE)
    {
        if(FM17522_Read_Reg(Status2Reg) & 0x08) //判断加密标志位,确认认证结果
            return TRUE;
        else
            return FALSE;
    }

    return FALSE;
}


06.jpg

其实用这个软件也就大概用这几个地方,编译,调试和下载,调试的话用官方例程的话几乎不需要修改,所以非常容易就可以上手。
在写代码的时候用memcpy会出现问题,有一些警告,这个可以通过添加#include <string.h>来解决。还有个问题就是我用这个语句赋值的时候,会有警告。memcpy(uid,rece_buff, 5);,警告内容为:warning: passing argument 1 of'memcpy' makes pointer from integer without a cast [-Wint-conversion]。也不知道为什么,最后换了一种方式,采用for循环的方式赋值解决了。

QQ截图20220331004308.jpg
最后分享一下效果吧,小密说如果LED是全亮或者全灭这样效果更加明显,可是我懒了,哈哈哈,就没改。
最后感谢小管家这个给力的活动,还让我学会了新技能,奈斯。

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 50.00 元 2022-03-31
理由:恭喜通过原创文章审核!请多多加油哦!

foxsbig| | 2022-4-8 15:30 | 显示全部楼层
很nice的帖子,风趣幽默,又有干货

使用特权

评论回复
yangxiaor520| | 2022-4-13 09:03 | 显示全部楼层
下次可以直接上传代码文件

使用特权

评论回复
littlelida| | 2022-4-15 16:52 | 显示全部楼层
白菜价,哈哈哈

使用特权

评论回复
发新帖 本帖赏金 50.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则