• RC522射频卡读写模块驱动(仅读取)


    说明

    更改了网上的源代码,仅保留了读取序列号并通过串口回传的功能。版本号:V1
    感谢 https://blog.csdn.net/qq_28877125/article/details/80437095

    测试结果

    main

    
    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "lcd.h"
    #include "RC522.h"
    
    int main(void)
    { 
    	unsigned char ID[4],i;
    
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    	delay_init(168);      //初始化延时函数
    	uart_init(115200);	  //初始化串口波特率为115200
    	RC522_Init();
    
      	while(1) 
    	{		
    		if(RC522_ReadCard(ID))
    		{
    			for(i=0;i<4;i++)
    			{
    				printf("%x",ID[i]);
    			}
    			printf("
    ");
    		}
    	}
    }
    
    

    RC522.h

    /******************************************************************************
    * @File     RC522.h
    * @Author   Velscode
    * @Date     2019/01
    * @Email    velscode@gmail.com
    * @Version  1.0
    ******************************************************************************/
    #ifndef _RC522_H_
    #define _RC522_H_
    
    #include "sys.h" 
    #include "stm32f4xx_it.h"
    
    /*******************************
     * 连线说明:
     * 1 -- SDA  <----->PA4
     * 2 -- SCK  <----->PA5
     * 3 -- MOSI <----->PA7
     * 4 -- MISO <----->PA6
     * 5 -- 悬空
     * 6 -- GND <----->GND
     * 7 -- RST <----->PB0
     * 8 -- VCC <----->VCC
    ************************************/
    
    /* IO口宏定义 ----------------------------------------------------------------------- */
    #define          RC522_CS_Enable()         GPIO_ResetBits( GPIOA, GPIO_Pin_4 )
    #define          RC522_CS_Disable()        GPIO_SetBits  ( GPIOA, GPIO_Pin_4 )
    
    #define          RC522_Reset_Enable()      GPIO_ResetBits( GPIOB, GPIO_Pin_0 )
    #define          RC522_Reset_Disable()     GPIO_SetBits  ( GPIOB, GPIO_Pin_0 )
     
    #define          RC522_SCK_0()             GPIO_ResetBits( GPIOA, GPIO_Pin_5 )
    #define          RC522_SCK_1()             GPIO_SetBits  ( GPIOA, GPIO_Pin_5 )
    
    #define          RC522_MOSI_0()            GPIO_ResetBits( GPIOA, GPIO_Pin_7 )
    #define          RC522_MOSI_1()            GPIO_SetBits  ( GPIOA, GPIO_Pin_7 )
    
    #define          RC522_MISO_GET()          GPIO_ReadInputDataBit ( GPIOA, GPIO_Pin_6 )
    
    /* 函数声明 ---------------------------------------------------- */
    u8   RC522_isConnected( void );	                //检查模块连接
    void RC522_Init ( void );		                //初始化
    void RC522_WriteRawRC ( u8 Address, u8 Value );	//写寄存器
    u8   RC522_ReadRawRC  ( u8 Address );			//读寄存器
    u8   RC522_ReadCard( unsigned char *ID );		//读卡
    
    
    /* MF522 命令字 ------------------------------------------------- */
    #define PCD_IDLE              0x00               //取消当前命令
    #define PCD_AUTHENT           0x0E               //验证密钥
    #define PCD_RECEIVE           0x08               //接收数据
    #define PCD_TRANSMIT          0x04               //发送数据
    #define PCD_TRANSCEIVE        0x0C               //发送并接收数据
    #define PCD_RESETPHASE        0x0F               //复位
    #define PCD_CALCCRC           0x03               //CRC计算
    
    
    /* ifare_One卡片命令字 ---------------------------------------------------- */
    #define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
    #define PICC_REQALL           0x52               //寻天线区内全部卡
    #define PICC_ANTICOLL1        0x93               //防冲撞
    #define PICC_ANTICOLL2        0x95               //防冲撞
    #define PICC_AUTHENT1A        0x60               //验证A密钥
    #define PICC_AUTHENT1B        0x61               //验证B密钥
    #define PICC_READ             0x30               //读块
    #define PICC_WRITE            0xA0               //写块
    #define PICC_DECREMENT        0xC0               //扣款
    #define PICC_INCREMENT        0xC1               //充值
    #define PICC_RESTORE          0xC2               //调块数据到缓冲区
    #define PICC_TRANSFER         0xB0               //保存缓冲区中数据
    #define PICC_HALT             0x50               //休眠
    
    
    /* MF522 FIFO--------------------------- */
    #define DEF_FIFO_LENGTH       64
    #define MAXRLEN               18
    
    /* MF522寄存器 ------------------------- */
    // PAGE 0
    #define     RFU00                 0x00    
    #define     CommandReg            0x01    
    #define     ComIEnReg             0x02    
    #define     DivlEnReg             0x03    
    #define     ComIrqReg             0x04    
    #define     DivIrqReg             0x05
    #define     ErrorReg              0x06    
    #define     Status1Reg            0x07    
    #define     Status2Reg            0x08    
    #define     FIFODataReg           0x09
    #define     FIFOLevelReg          0x0A
    #define     WaterLevelReg         0x0B
    #define     ControlReg            0x0C
    #define     BitFramingReg         0x0D
    #define     CollReg               0x0E
    #define     RFU0F                 0x0F
    // PAGE 1     
    #define     RFU10                 0x10
    #define     ModeReg               0x11
    #define     TxModeReg             0x12
    #define     RxModeReg             0x13
    #define     TxControlReg          0x14
    #define     TxAutoReg             0x15
    #define     TxSelReg              0x16
    #define     RxSelReg              0x17
    #define     RxThresholdReg        0x18
    #define     DemodReg              0x19
    #define     RFU1A                 0x1A
    #define     RFU1B                 0x1B
    #define     MifareReg             0x1C
    #define     RFU1D                 0x1D
    #define     RFU1E                 0x1E
    #define     SerialSpeedReg        0x1F
    // PAGE 2    
    #define     RFU20                 0x20  
    #define     CRCResultRegM         0x21
    #define     CRCResultRegL         0x22
    #define     RFU23                 0x23
    #define     ModWidthReg           0x24
    #define     RFU25                 0x25
    #define     RFCfgReg              0x26
    #define     GsNReg                0x27
    #define     CWGsCfgReg            0x28
    #define     ModGsCfgReg           0x29
    #define     TModeReg              0x2A
    #define     TPrescalerReg         0x2B
    #define     TReloadRegH           0x2C
    #define     TReloadRegL           0x2D
    #define     TCounterValueRegH     0x2E
    #define     TCounterValueRegL     0x2F
    // PAGE 3      
    #define     RFU30                 0x30
    #define     TestSel1Reg           0x31
    #define     TestSel2Reg           0x32
    #define     TestPinEnReg          0x33
    #define     TestPinValueReg       0x34
    #define     TestBusReg            0x35
    #define     AutoTestReg           0x36
    #define     VersionReg            0x37
    #define     AnalogTestReg         0x38
    #define     TestDAC1Reg           0x39  
    #define     TestDAC2Reg           0x3A   
    #define     TestADCReg            0x3B   
    #define     RFU3C                 0x3C   
    #define     RFU3D                 0x3D   
    #define     RFU3E                 0x3E   
    #define     RFU3F		  		  0x3F
    
    /* 通信返回码 ----------------------- */
    #define 	MI_OK                 0
    #define 	MI_NOTAGERR           1
    #define 	MI_ERR                2
    
    #endif
    /* End of File ------------------------------------------------------------- */
    
    

    RC522.c

    /******************************************************************************
    * @File     RC522.c
    * @Author   Velscode
    * @Date     2019/01
    * @Email    velscode@gmail.com
    * @Version  1.0
    ******************************************************************************/
    #include "sys.h"
    #include "RC522.h"
    #include "delay.h"
    
    
    char          PcdAnticoll ( u8 * pSnr );
    void          PcdAntennaOn ( void );
    char          PcdComMF522 ( u8 ucCommand, u8 * pInData, u8 ucInLenByte, u8 * pOutData, u32 * pOutLenBit );
    
    void          SetBitMask ( u8 Reg, u8 Mask );
    void          ClearBitMask ( u8 Reg, u8 Mask );
    
    void          SPI_RC522_SendByte ( u8 byte );
    unsigned char SPI_RC522_ReadByte ( void );
    
    /********************************************
    * @Name  RC522_ReadCard
    * @Brief 读取射频卡
    * @Para  如果读取成功,ID中存储的就是卡序列号
    * @Retun 1 - 读取到ID卡
    *        0 - 未读取到ID卡
    ********************************************/
    u8 RC522_ReadCard( unsigned char *ID )
    {
    	u8 state = 0x00;
    	  
        u8 ucComMF522Buf [ MAXRLEN ]; 
        u32 ulLen;
    
        ClearBitMask ( Status2Reg, 0x08 );	//清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
        RC522_WriteRawRC ( BitFramingReg, 0x07 );	//发送的最后一个字节的 七位
        SetBitMask ( TxControlReg, 0x03 );	//TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
    
        ucComMF522Buf [ 0 ] = PICC_REQALL;		//存入 卡片命令字
    
        state = PcdComMF522 ( PCD_TRANSCEIVE,	ucComMF522Buf, 1, ucComMF522Buf, & ulLen );	//寻卡  
    	
    	if(state==MI_OK)//寻卡成功
        {
            state = MI_ERR;
            state = PcdAnticoll(ID);//防冲撞	      
        }
    	
    	if( state == MI_OK )
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    /***********************************
    * @Name  RC522_isConnected()
    * @Brief 检查RC522模块是否连接
    * @Retun 1 - 连接成功
    *        0 - 连接失败
    ************************************/
    u8 RC522_isConnected(void)
    {
    	if(RC522_ReadRawRC(VersionReg)==0x92)
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    /*******************************
    * @Name RC522_Init()
    * @Brief 初始化RC522
    ************************************/
    void RC522_Init( void )
    {
    	// GPIO初始化 ------------------------------------------------------------------------------
    	GPIO_InitTypeDef GPIO_InitStructure;                                        //结构体定义
    	
    	RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB , ENABLE );//使能GPIOAB时钟
    	
    	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;			//输出模式
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		//100MHZ速率
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;		//不拉
    	
    	// CS
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;	 
        GPIO_Init(GPIOA, &GPIO_InitStructure);					//使用给定参数初始化引脚
        
        // SCK
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	 
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // MOSI
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;	 
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // RST
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	 
        GPIO_Init(GPIOB, &GPIO_InitStructure);
    	
    	// MISO
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;	 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;	//MISO引脚配置为输入模式,其它不变
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	//其它操作 ----------------------------------
    	RC522_Reset_Disable();
    	RC522_CS_Disable();
    	
    	//复位RC522 ---------------------------------
    	RC522_Reset_Disable();
        delay_us ( 1 );
    	
        RC522_Reset_Enable();
        delay_us ( 1 );
    
        RC522_Reset_Disable();
        delay_us ( 1 );
    
        RC522_WriteRawRC ( CommandReg, 0x0f );
    
        while ( RC522_ReadRawRC ( CommandReg ) & 0x10 );
    
        delay_us ( 1 );
    
        RC522_WriteRawRC ( ModeReg, 0x3D );            //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
    
        RC522_WriteRawRC ( TReloadRegL, 30 );          //16位定时器低位    
        RC522_WriteRawRC ( TReloadRegH, 0 );			 //16位定时器高位
    
        RC522_WriteRawRC ( TModeReg, 0x8D );			 //定义内部定时器的设置
    
        RC522_WriteRawRC ( TPrescalerReg, 0x3E );		 //设置定时器分频系数
    
        RC522_WriteRawRC ( TxAutoReg, 0x40 );			 //调制发送信号为100%ASK	
    	
    	//设置RC522工作方式为ISO14443_A标准 -----------------------------------------------------
    	ClearBitMask ( Status2Reg, 0x08 );
    		
    	RC522_WriteRawRC ( ModeReg, 0x3D );//3F
    	
    	RC522_WriteRawRC ( RxSelReg, 0x86 );//84
    	
    	RC522_WriteRawRC( RFCfgReg, 0x7F );   //4F
    	
    	RC522_WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
    	
    	RC522_WriteRawRC ( TReloadRegH, 0 );
    	
    	RC522_WriteRawRC ( TModeReg, 0x8D );
    	
    	RC522_WriteRawRC ( TPrescalerReg, 0x3E );
    	
    	delay_us ( 20 );
    	
    	PcdAntennaOn ();//开天线
    }
    
    /*********************************************
     * @Name   SPI_RC522_SendByte
     * @brief  向RC522发送1 字节数据
     * @input  byte,要发送的数据
     * @note   RC522.c内部函数
     *********************************************/
    void SPI_RC522_SendByte ( u8 byte )
    {
        unsigned char i;
    	
        for( i = 0; i < 8; i++ )
        {     
    			if ( byte & 0x80 )
    					RC522_MOSI_1();
    			else 
    					RC522_MOSI_0();
    
    			delay_us ( 50 );
    		
    			RC522_SCK_0 ();
    
    			delay_us ( 50 );
    			 
    			RC522_SCK_1();
    
    			delay_us ( 50 );
    			 
    			byte <<= 1; 
        } 
    }
    
    /*********************************************
     * @Name    SPI_RC522_ReadByte
     * @Brief   读取RC522 1字节数据
     * @Para    RC522回传的数据
     * @Note    RC522.c内部函数
     *********************************************/
    u8 SPI_RC522_ReadByte ( void )
    {
    	u8 i;
    	u8 SPI_Data;
    
    	for( i = 0; i < 8; i++ )
    	{
    		SPI_Data <<= 1;
     
    		RC522_SCK_0();
    		delay_us ( 50 );
    	
    		if ( RC522_MISO_GET() == 1)
    				SPI_Data |= 0x01;
    		delay_us ( 50 );
    
    		RC522_SCK_1();
    		delay_us ( 50 );
    		
    	}
    	return SPI_Data;
    }
    
    /*********************************************
     * @Name    RC522_WriteRawRC
     * @Brief   写RC522寄存器
     * @Para    Address 寄存器地址
     * @Para    Value   要写入的值
     *********************************************/
    void RC522_WriteRawRC ( u8 Address, u8 Value )
    {  
    	u8 Addr;
    
    	Addr = ( Address << 1 ) & 0x7E;
    	
    	RC522_CS_Enable();
    	
    	SPI_RC522_SendByte ( Addr );
    	
    	SPI_RC522_SendByte ( Value );
    	
    	RC522_CS_Disable();	
    }
    
    /*********************************************
     * @Name    RC522_ReadRawRC
     * @Brief   读RC522寄存器
     * @Para    Address 寄存器地址
     * @Retun   寄存器中的知
     *********************************************/
    u8 RC522_ReadRawRC ( u8 Address )
    {
    	u8 Addr, Value;
    	
    	
    	Addr = ( ( Address << 1 ) & 0x7E ) | 0x80;
    	
    	RC522_CS_Enable();
    	
    	SPI_RC522_SendByte ( Addr );
    	
    	Value = SPI_RC522_ReadByte ();
    	
    	RC522_CS_Disable();
    
    	return Value;
    }
    
    /*********************************************
     * @Name    SetBitMask
     * @Brief   设置寄存器指定位
     * @Para    Reg  寄存器地址
     * @Para    Mask 
     *********************************************/
    void SetBitMask ( u8 Reg, u8 Mask )  
    {
        u8 Temp;
    
        Temp = RC522_ReadRawRC ( Reg );
    	
        RC522_WriteRawRC ( Reg, Temp | Mask );         // set bit mask
    
    }
    
    
    /*********************************************
     * @Name    ClearBitMask
     * @Brief   清除寄存器指定位
     * @Para    Reg  寄存器地址
     * @Para    Mask 
     *********************************************/
    void ClearBitMask ( u8 Reg, u8 Mask )  
    {
        u8 Temp;
    
        Temp = RC522_ReadRawRC ( Reg );
    	
        RC522_WriteRawRC ( Reg, Temp & ( ~ Mask) );  // clear bit mask
    }
    
    /*********************************************
     * @Name    PcdAntennaOn
     * @Brief   开启天线
     * @Note	有待评估该函数是否必须
     *********************************************/
    void PcdAntennaOn ( void )
    {
        u8 uc;
    
        uc = RC522_ReadRawRC ( TxControlReg );
    	
        if ( ! ( uc & 0x03 ) )
    			SetBitMask(TxControlReg, 0x03);
    	
    }
    
    /*
     * 函数名:PcdAnticoll
     * 描述  :防冲撞
     * 输入  :pSnr,卡片序列号,4字节
     * 返回  : 状态值
     *         = MI_OK,成功
     * 调用  :外部调用
     */
    char PcdAnticoll ( u8 * pSnr )
    {
        char cStatus;
        u8 uc, ucSnr_check = 0;
        u8 ucComMF522Buf [ MAXRLEN ]; 
    	u32 ulLen;
    
        ClearBitMask ( Status2Reg, 0x08 );		//清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
        RC522_WriteRawRC ( BitFramingReg, 0x00);		//清理寄存器 停止收发
        ClearBitMask ( CollReg, 0x80 );			//清ValuesAfterColl所有接收的位在冲突后被清除
       
        ucComMF522Buf [ 0 ] = 0x93;	//卡片防冲突命令
        ucComMF522Buf [ 1 ] = 0x20;
       
        cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, & ulLen);//与卡片通信
    	
        if ( cStatus == MI_OK)		//通信成功
        {
    		for ( uc = 0; uc < 4; uc ++ )
            {
                * ( pSnr + uc )  = ucComMF522Buf [ uc ];			//读出UID
                ucSnr_check ^= ucComMF522Buf [ uc ];
            }
    			
            if ( ucSnr_check != ucComMF522Buf [ uc ] )
            		cStatus = MI_ERR;    
    				 
        }
        
        SetBitMask ( CollReg, 0x80 );
    
        return cStatus;
    	
    }
    
    
    /*
     * 函数名:PcdComMF522
     * 描述  :通过RC522和ISO14443卡通讯
     * 输入  :ucCommand,RC522命令字
     *         pInData,通过RC522发送到卡片的数据
     *         ucInLenByte,发送数据的字节长度
     *         pOutData,接收到的卡片返回数据
     *         pOutLenBit,返回数据的位长度
     * 返回  : 状态值
     *         = MI_OK,成功
     * 调用  :内部调用
     */
    char PcdComMF522 ( u8 ucCommand, u8 * pInData, u8 ucInLenByte, u8 * pOutData, u32 * pOutLenBit )		
    {
        char cStatus = MI_ERR;
        u8 ucIrqEn   = 0x00;
        u8 ucWaitFor = 0x00;
        u8 ucLastBits;
        u8 ucN;
        u32 ul;
    
        switch ( ucCommand )
        {
           case PCD_AUTHENT:		//Mifare认证
              ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEn
              ucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位
              break;
    			 
           case PCD_TRANSCEIVE:		//接收发送 发送接收
              ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
              ucWaitFor = 0x30;		//寻卡等待时候 查询接收中断标志位与 空闲中断标志位
              break;
    			 
           default:
             break;
    			 
        }
       
        RC522_WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );		//IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
        ClearBitMask ( ComIrqReg, 0x80 );			//Set1该位清零时,CommIRqReg的屏蔽位清零
        RC522_WriteRawRC ( CommandReg, PCD_IDLE );		//写空闲命令
        SetBitMask ( FIFOLevelReg, 0x80 );			//置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
        
        for ( ul = 0; ul < ucInLenByte; ul ++ )
    		  RC522_WriteRawRC ( FIFODataReg, pInData [ ul ] );    		//写数据进FIFOdata
    			
        RC522_WriteRawRC ( CommandReg, ucCommand );					//写命令
       
        
        if ( ucCommand == PCD_TRANSCEIVE )
    			SetBitMask(BitFramingReg,0x80);  				//StartSend置位启动数据发送 该位与收发命令使用时才有效
        
        ul = 1000;//根据时钟频率调整,操作M1卡最大等待时间25ms
    		
        do 														//认证 与寻卡等待时间	
        {
             ucN = RC522_ReadRawRC ( ComIrqReg );							//查询事件中断
             ul --;
        } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );		//退出条件i=0,定时器中断,与写空闲命令
    		
        ClearBitMask ( BitFramingReg, 0x80 );					//清理允许StartSend位
    		
        if ( ul != 0 )
        {
    		if ( ! (( RC522_ReadRawRC ( ErrorReg ) & 0x1B )) )			//读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
    		{
    			cStatus = MI_OK;
    			
    			if ( ucN & ucIrqEn & 0x01 )					//是否发生定时器中断
    			  cStatus = MI_NOTAGERR;   
    				
    			if ( ucCommand == PCD_TRANSCEIVE )
    			{
    				ucN = RC522_ReadRawRC ( FIFOLevelReg );			//读FIFO中保存的字节数
    				
    				ucLastBits = RC522_ReadRawRC ( ControlReg ) & 0x07;	//最后接收到得字节的有效位数
    				
    				if ( ucLastBits )
    					* pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;   	//N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
    				else
    					* pOutLenBit = ucN * 8;   					//最后接收到的字节整个字节有效
    				
    				if ( ucN == 0 )	
                        ucN = 1;    
    				
    				if ( ucN > MAXRLEN )
    					ucN = MAXRLEN;   
    				
    				for ( ul = 0; ul < ucN; ul ++ )
    				  pOutData [ ul ] = RC522_ReadRawRC ( FIFODataReg );   
    			}		
            }
    			else
    				cStatus = MI_ERR;   
        }
       
       SetBitMask ( ControlReg, 0x80 );           // stop timer now
       RC522_WriteRawRC ( CommandReg, PCD_IDLE ); 
    	
       return cStatus;
    
    }
    
    /* End of File ------------------------------------------------------------- */
    
    
  • 相关阅读:
    django之表多对多查询
    Django之ORMselect_related和prefetch_related
    django中用户登入时初始化session中保存的数据
    django中间件判断用户有无权限访问当前的url
    django中自定议rbac权限model类
    django中的inclusion_tag配置和实现
    docker命令
    JS设置cookie、读取cookie、删除cookie
    MySQL Community Downloads
    44个CSS3制作的形状图形
  • 原文地址:https://www.cnblogs.com/velscode/p/10291711.html
Copyright © 2020-2023  润新知