C语言代码注释➕流程图

需要详细的c语言代码注释以及流程图,最好每一行都有注释,非常感谢,时间有限自己短时间内难以理解。


#include "RC522.h"



/////////////////////////////////////////////////////////////////////
//功    能:寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]:卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
   char status;  
   unsigned int  unLen;
   unsigned char ucComMF522Buf[MAXRLEN]; 

   ClearBitMask(Status2Reg,0x08);
   WriteRawRC(BitFramingReg,0x07);
   SetBitMask(TxControlReg,0x03);
 
   ucComMF522Buf[0] = req_code;

   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
   
   if ((status == MI_OK) && (unLen == 0x10))
   {    
       *pTagType     = ucComMF522Buf[0];
       *(pTagType+1) = ucComMF522Buf[1];
   }
   else
   {   
        status = MI_ERR;  
    }
   
   return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:复位RC522
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
    //unsigned char i;
    MF522_RST=1;

        _nop_();                  

    MF522_RST=0;

        _nop_();                                
    
    WriteRawRC(CommandReg,PCD_RESETPHASE);

        _nop_();                  
    
    
    WriteRawRC(ModeReg,0x3D);            //和Mifare卡通讯,CRC初始值0x6363
    WriteRawRC(TReloadRegL,30);           
    WriteRawRC(TReloadRegH,0);
    WriteRawRC(TModeReg,0x8D);
    WriteRawRC(TPrescalerReg,0x3E);
   WriteRawRC(TxAutoReg,0x40);
    return MI_OK;
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
    ClearBitMask(TxControlReg, 0x03);
}
void PcdAntennaOn(void)
{
    unsigned char i;
    i = ReadRawRC(TxControlReg);
    if (i & 0x03)
    {
        SetBitMask(TxControlReg, 0x03);
    }
}

/////////////////////////////////////////////////////////////////////
//功    能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr)
{
    char status;
    unsigned char i,snr_check=0;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    

    ClearBitMask(Status2Reg,0x08);
    WriteRawRC(BitFramingReg,0x00);
    ClearBitMask(CollReg,0x80);
 
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)
    {
         for (i=0; i<4; i++)
         {   
             *(pSnr+i)  = ucComMF522Buf[i];
             snr_check ^= ucComMF522Buf[i];

         }
         if (snr_check = ucComMF522Buf[i])
         {   status = MI_ERR;    }
    }
    
    SetBitMask(CollReg,0x80);
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}

/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char i, ucAddr;

    MF522_SCK = 0;
    MF522_NSS = 0;
    ucAddr = ((Address<<1)&0x7E);

    for(i=8;i>0;i--)
    {
        MF522_SI = ((ucAddr&0x80)==0x80);
        MF522_SCK = 1;
        ucAddr <<= 1;

    }

    for(i=8;i>0;i--)
    {
        MF522_SI = ((value&0x80)==0x80);
        MF522_SCK = 1;
        value <<= 1;
    }
    MF522_NSS = 0;
    MF522_SCK = 0;
}
/////////////////////////////////////////////////////////////////////
//功    能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg,tmp | mask);  // set bit mask
}

/////////////////////////////////////////////////////////////////////
//功    能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
//          pInData[IN]:通过RC522发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOutData[OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command, 
                 unsigned char *pInData, 
                 unsigned char InLenByte,
                 unsigned char *pOutData, 
                 unsigned int  *pOutLenBit)
{
    char status = MI_ERR;
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    switch (Command)
    {
       case PCD_AUTHENT:
          irqEn   = 0x12;
          waitFor = 0x10;
          break;
       case PCD_TRANSCEIVE:
          irqEn   = 0x77;
          waitFor = 0x30;
          break;
default:
         break;
    }
   
    WriteRawRC(ComIEnReg,irqEn|0x80);
    ClearBitMask(ComIrqReg,0x80);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);
    
    for (i=0; i<InLenByte; i++)
    {   WriteRawRC(FIFODataReg, pInData[i]);    }
    WriteRawRC(CommandReg, Command);
   
    
    if (Command == PCD_TRANSCEIVE)
    {    SetBitMask(BitFramingReg,0x80);  }
    
    i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
    do 
    {
         n = ReadRawRC(ComIrqReg);
         i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));
    ClearBitMask(BitFramingReg,0x80);
          
    if (i!=0)
    {    
         if(!(ReadRawRC(ErrorReg)&0x1B))
         {
             status = MI_OK;
             if (n & irqEn & 0x01)
             {   status = MI_NOTAGERR;   }
             if (Command == PCD_TRANSCEIVE)
             {
                   n = ReadRawRC(FIFOLevelReg);
                  lastBits = ReadRawRC(ControlReg) & 0x07;
                if (lastBits)
                {   *pOutLenBit = (n-1)*8 + lastBits;   }
                else
                {   *pOutLenBit = n*8;   }
                if (n == 0)
                {   n = 1;    }
                if (n > MAXRLEN)
                {   n = MAXRLEN;   }
                for (i=0; i<n; i++)
                {   pOutData[i] = ReadRawRC(FIFODataReg);    }
            }
         }
         else
         {   status = MI_ERR;   }
        
   }
   

   SetBitMask(ControlReg,0x80);           // stop timer now
   WriteRawRC(CommandReg,PCD_IDLE); 
   return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
     unsigned char i, ucAddr;
     unsigned char ucResult=0;

     MF522_SCK = 0;
     MF522_NSS = 0;
     ucAddr = ((Address<<1)&0x7E)|0x80;

     for(i=8;i>0;i--)
     {
        MF522_SI = ((ucAddr&0x80)==0x80);
         MF522_SCK = 1;
         ucAddr <<= 1;
         MF522_SCK = 0;
     }

     for(i=8;i>0;i--)
     {
         MF522_SCK = 1;
         ucResult <<= 1;
         ucResult|=(bit)MF522_SO;
         MF522_SCK = 0;
     }

     MF522_NSS = 1;
     MF522_SCK = 1;
     return ucResult;
}
//返回读到的IC号g_ucTempbuf[0]-[3]
unsigned char ReadICcode(unsigned char *g_ucTempbuf)
{
    unsigned char status;
    //while(status != MI_OK)
    {
        //RC522_Init( );
        PcdReset();
        PcdAntennaOff(); 
        PcdAntennaOn();
        status = PcdRequest(PICC_REQALL, g_ucTempbuf);//寻卡
        
        if (status == MI_OK)
            status = PcdAnticoll(g_ucTempbuf);//防冲撞
        
        if (status == MI_OK)return 0;
        else return 1;
    }
        
}

基于new bing的注释参考:
这份代码是一个基于RC522 RFID读卡器的驱动程序,主要包含以下几个函数:

  1. PcdRequest:用于寻卡,输入参数为寻卡方式和指向卡片类型代码的指针,输出成功或失败状态。
  1. PcdReset:复位RC522,返回成功或失败状态。
  1. PcdAntennaOff/PcdAntennaOn:关闭/打开天线。
  1. PcdAnticoll:防冲撞,输入指向卡片序列号的指针,返回成功或失败状态。
  1. ClearBitMask/SetBitMask:清/置RC522寄存器位,输入寄存器地址和清/置位值。
  1. WriteRawRC/ReadRawRC:写/读RC522寄存器,输入寄存器地址和写入/读出的值。
  1. PcdComMF522:通过RC522和ISO14443卡通讯,输入RC522命令字、待发送数据、发送数据字节长度、接收数据缓冲区和返回数据位长度指针,返回成功或失败状态。

此外,还包含一个ReadICcode函数,用于寻找IC卡并将卡号保存到指定缓冲区。

【大致流程图:】

img

【代码注释】


#include "RC522.h"
 
 
 
/////////////////////////////////////////////////////////////////////
//功    能:寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]:卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
// 函数名:char PcdRequest(unsigned char req_code,unsigned char *pTagType)
// 功能:实现RC522发送寻卡命令,并返回卡片类型
// 参数:
//   req_code:寻卡方式,0x52为请求所有卡,0x26为请求感应区内所有卡
//   *pTagType:指向卡片类型代码的指针,两个字节
// 返回值:
//   MI_OK: 成功
//   MI_ERR: 失败
char PcdRequest(unsigned char req_code, unsigned char *pTagType)
{
    char status;  // 返回值,表示操作状态
    unsigned int unLen;  // 接收到的数据长度
    unsigned char ucComMF522Buf[MAXRLEN];  // 缓冲区,用于读写RC522寄存器

    ClearBitMask(Status2Reg, 0x08);  // 清除冲突标志位
    WriteRawRC(BitFramingReg, 0x07);  // 最后一个字节传输7位
    SetBitMask(TxControlReg, 0x03);  // 启动发送

    ucComMF522Buf[0] = req_code;  // 命令码

    // 发送命令并接受卡片回复
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen);

    if ((status == MI_OK) && (unLen == 0x10)) // 根据接受到的数据判断操作是否成功
    {

        // 保存卡片类型到指定缓冲区
        *pTagType     = ucComMF522Buf[0];
        *(pTagType+1) = ucComMF522Buf[1];
    }
    else
    {

        status = MI_ERR;  // 操作失败
    }

    // 返回操作状态
    return status;
}

/////////////////////////////////////////////////////////////////////
// 功能:复位RC522
// 返回值:成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
    //unsigned char i;
    MF522_RST=1;  // 将MF522的复位引脚置为高电平,准备复位

    _nop_();     // 稍作延时

    MF522_RST=0;  // 将MF522的复位引脚置为低电平,开始复位

    _nop_();     // 稍作延时

    WriteRawRC(CommandReg, PCD_RESETPHASE);  // 发送复位命令到MF522的CommandReg寄存器

    _nop_();     // 稍作延时

    // 初始化RC522的寄存器 
    WriteRawRC(ModeReg, 0x3D);            // 和Mifare卡通讯,CRC初始值0x6363
    WriteRawRC(TReloadRegL, 30);           
    WriteRawRC(TReloadRegH, 0);
    WriteRawRC(TModeReg, 0x8D);
    WriteRawRC(TPrescalerReg, 0x3E);
    WriteRawRC(TxAutoReg, 0x40);

    return MI_OK;  // 返回操作状态 
}
/////////////////////////////////////////////////////////////////////
// 关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
     ClearBitMask(TxControlReg, 0x03);  // 清零TxControlReg寄存器的最后两位,关闭天线
}

/////////////////////////////////////////////////////////////////////
// 打开天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void)
{
    unsigned char i;
    i = ReadRawRC(TxControlReg);  // 读取TxControlReg寄存器的值
    if (i & 0x03)  // 如果TxControlReg寄存器的最后两位是1,则表示天线已经打开
    {
         SetBitMask(TxControlReg, 0x03);  // 将TxControlReg寄存器的最后两位设置为1,继续打开天线
    }
}
/////////////////////////////////////////////////////////////////////
// 功能:防冲撞,获取卡片序列号
// 参数说明:
//   pSnr[OUT]: 卡片序列号,4字节
// 返回值:成功返回MI_OK,失败返回MI_ERR
/////////////////////////////////////////////////////////////////////

char PcdAnticoll(unsigned char *pSnr)
{
    char status;  // 操作状态
    unsigned char i,snr_check=0;  // snr_check用于校验读取到的卡片序列号是否正确
    unsigned int  unLen;  // 用于存储接收到的数据长度
    unsigned char ucComMF522Buf[MAXRLEN];  // 存储发送和接收的数据缓冲区

    // 向Status2Reg寄存器的最后一位写0,清除上次发送时产生的冲突标志位
    ClearBitMask(Status2Reg,0x08);
    // 向BitFramingReg寄存器写0,表示不需要接收数据帧的最后一个字节
    WriteRawRC(BitFramingReg,0x00);
    // 向CollReg寄存器的最高位写0,设置为检测所有卡片
    ClearBitMask(CollReg,0x80);

    ucComMF522Buf[0] = PICC_ANTICOLL1;  // 发送防冲撞命令
    ucComMF522Buf[1] = 0x20;  // 目标卡片序列号长度为4字节

    // 向MF522发送防冲撞命令,并等待MF522应答
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)  // 如果返回状态为MI_OK,则表示防冲撞成功
    {
        for (i=0; i<4; i++)  // 读取卡片序列号
        {   
            *(pSnr+i)  = ucComMF522Buf[i];
            snr_check ^= ucComMF522Buf[i];  // 计算校验和
        }
        if (snr_check = ucComMF522Buf[i])  // 比较读取到的卡片序列号和校验和是否相同
        {   
            status = MI_ERR;  // 如果校验和不匹配,则返回MI_ERR
        }
    }

    SetBitMask(CollReg,0x80);  // 向CollReg寄存器的最高位写1,恢复默认值
    return status;  // 返回操作状态
}
/////////////////////////////////////////////////////////////////////
// 功能:清除RC522芯片寄存器指定位
// 参数说明:
//   reg[IN]: 寄存器地址
//   mask[IN]: 清零的位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg, unsigned char mask)
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);  // 读取寄存器原始值
    WriteRawRC(reg, tmp & ~mask);  // 将需要清零的位与寄存器原始值取反进行位与操作,结果写入寄存器中
    // 这里涉及按位与和按位取反两个操作,用来清除寄存器中指定的位
}
/////////////////////////////////////////////////////////////////////
// 功能:向RC522芯片寄存器中写入值
// 参数说明:
//   Address[IN]: 寄存器地址
//   value[IN]: 写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{

    unsigned char i, ucAddr;

    MF522_SCK = 0;
    MF522_NSS = 0;
    ucAddr = ((Address<<1)&0x7E);  // 将需要写入的寄存器地址左移一位,并清除最高位,得到ucAddr

    for(i=8;i>0;i--)
    {
        MF522_SI = ((ucAddr&0x80)==0x80); // 判断ucAddr最高位是否为1,如果是则将MF522_SI置1,否则清零
        MF522_SCK = 1;  // 将MF522_SCK置1
        ucAddr <<= 1;  // 将ucAddr左移一位
    }

    for(i=8;i>0;i--)
    {
        MF522_SI = ((value&0x80)==0x80);  // 判断value最高位是否为1,如果是则将MF522_SI置1,否则清零
        MF522_SCK = 1;  // 将MF522_SCK置1
        value <<= 1;  // 将value左移一位
    }
    MF522_NSS = 0;  // 置MF522_NSS为0
    MF522_SCK = 0;  // 置MF522_SCK为0
}

/////////////////////////////////////////////////////////////////////
// 功能:向RC522芯片寄存器中设置指定位
// 参数说明:
//   reg[IN]: 寄存器地址
//   mask[IN]: 置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg, unsigned char mask)

{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);  // 读取寄存器原始值
    WriteRawRC(reg, tmp | mask);  // 将需要置1的位与寄存器原始值进行位或操作,结果写入寄存器中
    // 这里涉及按位或操作,用来设置寄存器中指定的位
}
/////////////////////////////////////////////////////////////////////
// 功能:通过RC522与ISO14443卡进行通讯
// 参数说明:
//   Command[IN]: RC522命令字
//   pInData[IN]: 发送的数据
//   InLenByte[IN]: 发送数据的字节长度
//   pOutData[OUT]: 接收到的卡片返回数据
//   *pOutLenBit[OUT]: 返回数据的位长度
/////////////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command,
unsigned char *pInData,
unsigned char InLenByte,
unsigned char *pOutData,
unsigned int  *pOutLenBit)
{
    char status = MI_ERR;  // 初始化状态为错误
    unsigned char irqEn   = 0x00;  // 定义中断控制寄存器里需要写入的值
    unsigned char waitFor = 0x00;  // 定义等待寄存器里需要写入的值
    unsigned char lastBits;  // 上一次通讯的位数
    unsigned char n;  // 定义计数器
    unsigned int i;  // 定义计数器
    switch (Command)  // 判断需要执行的指令类型
    {
        case PCD_AUTHENT:  // 如果需要验证卡片身份
        irqEn   = 0x12;  // 写入中断控制寄存器中的值,使能定时器和发送接收中断
        waitFor = 0x10;  // 写入等待寄存器中的值,表示等待发送接收中断
        break;
        case PCD_TRANSCEIVE:  // 如果需要发送和接收数据
        irqEn   = 0x77;  // 写入中断控制寄存器中的值,使能定时器和错误、发送、接收中断
        waitFor = 0x30;  // 写入等待寄存器中的值,表示等待发送接收中断和错误中断
        break;
        default:
        break;
    }

    WriteRawRC(ComIEnReg,irqEn|0x80);  // 向中断控制寄存器中写入值,使能中断输出,并打开定时器
    ClearBitMask(ComIrqReg,0x80);  // 在清空中断标志前,先禁止中断输出
    WriteRawRC(CommandReg,PCD_IDLE);  // 将命令寄存器中的值设为IDLE状态,即取消当前操作
    SetBitMask(FIFOLevelReg,0x80);  // 让FIFO缓冲区可以被写入数据

    for (i=0; i<InLenByte; i++)  // 依次向FIFO缓冲区内写入要发送的数据
    {   
        WriteRawRC(FIFODataReg, pInData[i]);  
    }

    WriteRawRC(CommandReg, Command);  // 将执行指令写入命令寄存器中

    if (Command == PCD_TRANSCEIVE)  // 如果是发送和接收数据的操作
    {    SetBitMask(BitFramingReg,0x80);  }  // 打开传输数据的标志位

    i = 600;  // 根据时钟频率调整,操作M1卡最大等待时间25ms
    do 
    {
        n = ReadRawRC(ComIrqReg);  // 读取中断标志寄存器中的值
        i--;  // 计数减1
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));  // 循环等待,直到发生中断或超时

    ClearBitMask(BitFramingReg,0x80);  // 关闭传输数据的标志位
        
    if (i!=0)  // 如果等待结束,说明接收到卡片返回的数据
    {    
        if(!(ReadRawRC(ErrorReg)&0x1B))  // 如果错误标志寄存器中没有错误信息
        {
            status = MI_OK;  // 状态设为成功
            if (n & irqEn & 0x01)
            {   status = MI_NOTAGERR;   }  // 接收到错误中断,则状态设为未检测到卡片
            if (Command == PCD_TRANSCEIVE)
            {
                n = ReadRawRC(FIFOLevelReg);  // 读取FIFO缓冲区的数据数量
                lastBits = ReadRawRC(ControlReg) & 0x07;  // 读取控制寄存器中的最后7位,即上一次剩余的位数
                if (lastBits)
                {   *pOutLenBit = (n-1)*8 + lastBits;   }  // 计算返回数据的长度
                else
                {   *pOutLenBit = n*8;   }  // 如果没有剩余的位数,则直接计算返回数据的长度
                if (n == 0)
                {   n = 1;    }  // 如果FIFO缓冲区中没有数据,则设置数据长度为1个字节
                if (n > MAXRLEN)
                {   n = MAXRLEN;   }  // 如果FIFO缓冲区中数据过多,则设置数据长度为最大值
                for (i=0; i<n; i++)
                {   pOutData[i] = ReadRawRC(FIFODataReg);    }  // 依次读取FIFO缓冲区中的数据,存储到输出缓冲区中
            }
        }
        else
        {   status = MI_ERR;   }  // 如果错误标志寄存器中有错误信息,则状态设为错误
    }

    SetBitMask(ControlReg,0x80);           // 禁止定时器,并停止其计数
    WriteRawRC(CommandReg,PCD_IDLE);  // 将命令寄存器中的值设为IDLE状态,即取消当前操作
    return status;  // 返回执行结果的状态
}
/////////////////////////////////////////////////////////////////////
// 功能:读取RC632寄存器的值
// 参数说明:
//   Address[IN]: 寄存器地址
// 返回值:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
    unsigned char i, ucAddr;
    unsigned char ucResult=0;

    MF522_SCK = 0;  // 将SCK信号线拉低,准备发送数据
    MF522_NSS = 0;  // 将NSS信号线拉低,开始从SPI总线发送数据
    ucAddr = ((Address<<1)&0x7E)|0x80;  // 将传入的地址左移一位,并设置第8位为1,表示读取寄存器的值

    for(i=8; i>0; i--)  // 循环8次,向SPI总线发送地址信息
    {
        MF522_SI = ((ucAddr&0x80)==0x80);  // 判断当前位是否为1,如果为1则将SDA信号线置高,反之则置低
        MF522_SCK = 1;  // 将SCK信号线拉高,使发送的数据稳定
        ucAddr <<= 1;  // 将地址信息向左移动一位,准备发送下一位
        MF522_SCK = 0;  // 将SCK信号线拉低,准备发送下一位数据
    }

    for(i=8;i>0;i--)  // 循环8次,从SPI总线接收返回的数据
    {
        MF522_SCK = 1;  // 将SCK信号线拉高,准备接收数据
        ucResult <<= 1;  // 将返回的数据向左移动一位
        ucResult |= (bit)MF522_SO;  // 判断SDO信号线是否为高电平,如果是则将ucResult当前位设置为1,反之则为0
        MF522_SCK = 0;  // 将SCK信号线拉低,准备接收下一位数据
    }

    MF522_NSS = 1;  // 将NSS信号线拉高,结束SPI总线通讯
    MF522_SCK = 1;  // 将SCK信号线拉高,保持通讯稳定
    return ucResult;  // 返回读取到的寄存器值
}

/////////////////////////////////////////////////////////////////////
// 功能:读取IC卡号
// 参数说明:
//   *g_ucTempbuf[OUT]: 存储IC卡号的数组指针
// 返回值:0表示读取成功,1表示读取失败
/////////////////////////////////////////////////////////////////////
unsigned char ReadICcode(unsigned char *g_ucTempbuf)
{
    unsigned char status;
    //while(status != MI_OK)
    {
    //RC522_Init( );
    PcdReset();  // 复位RC522
    PcdAntennaOff();  // 关闭天线
    PcdAntennaOn();  // 打开天线
    status = PcdRequest(PICC_REQALL, g_ucTempbuf);  // 寻卡

        if (status == MI_OK)
            status = PcdAnticoll(g_ucTempbuf);  // 防冲撞
        
        if (status == MI_OK)
            return 0;  // 如果读取成功,返回0
        else 
            return 1;  // 如果读取失败,返回1
    }
}

c语言程序设计流程图详解

可以借鉴下
https://blog.csdn.net/king110108/article/details/50420005

以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:

这段代码是用于控制RC522芯片与ISO14443卡通讯的,包括寻卡、防冲撞、读写数据等操作。下面是代码的注释和流程图:

#include "RC522.h" //包含头文件RC522.h

/////////////////////////////////////////////////////////////////////
//功    能:寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]:卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
   char status;  
   unsigned int  unLen;
   unsigned char ucComMF522Buf[MAXRLEN]; 

   ClearBitMask(Status2Reg,0x08);//清空Status2Reg的第4位
   WriteRawRC(BitFramingReg,0x07);//写BitFramingReg的值为0x07
   SetBitMask(TxControlReg,0x03);//设置TxControlReg的值为0x03
 
   ucComMF522Buf[0] = req_code;//将req_code赋值给ucComMF522Buf[0]

   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);//调用PcdComMF522函数

   if ((status == MI_OK) && (unLen == 0x10))
   {    
       *pTagType     = ucComMF522Buf[0];
       *(pTagType+1) = ucComMF522Buf[1];
   }
   else
   {   
        status = MI_ERR;  
  }
   
   return status;//返回status
}

/////////////////////////////////////////////////////////////////////
//功    能:复位RC522
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
    MF522_RST=1;//MF522_RST赋值为1

    _nop_();                  

    MF522_RST=0;//MF522_RST赋值为0

    _nop_();                                
    
    WriteRawRC(CommandReg,PCD_RESETPHASE);//写CommandReg的值为PCD_RESETPHASE

    WriteRawRC(ModeReg,0x3D);            //和Mifare卡通讯,CRC初始值0x6363
    WriteRawRC(TReloadRegL,30);           
    WriteRawRC(TReloadRegH,0);
    WriteRawRC(TModeReg,0x8D);
    WriteRawRC(TPrescalerReg,0x3E);
    WriteRawRC(TxAutoReg,0x40);
    return MI_OK;//返回MI_OK
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
    ClearBitMask(TxControlReg, 0x03);//清空TxControlReg的第01位
}

void PcdAntennaOn(void)
{
    unsigned char i;
    i = ReadRawRC(TxControlReg);
    if (i & 0x03)
    {
        SetBitMask(TxControlReg, 0x03);//设置TxControlReg的值为0x03
    }
}

/////////////////////////////////////////////////////////////////////
//功    能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr)
{
    char status;
    unsigned char i,snr_check=0;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ClearBitMask(Status2Reg,0x08);//清空Status2Reg的第4位
    WriteRawRC(BitFramingReg,0x00);//写BitFramingReg的值为0x00
    ClearBitMask(CollReg,0x80);//清空CollReg的第7位
 
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);//调用PcdComMF522函数

    if (status == MI_OK)
    {
        for (i=0; i<4; i++)
        {   
            *(pSnr+i)  = ucComMF522Buf[i];
            snr_check ^= ucComMF522Buf[i];

        }
        if (snr_check = ucComMF522Buf[i])
        {   status = MI_ERR;    }
    }
    
    SetBitMask(CollReg,0x80);//设置CollReg的第7return status;//返回status
}

/////////////////////////////////////////////////////////////////////
//功    能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}

/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char i, ucAddr;

    MF522_SCK = 0;
   

详细注释:

#include "RC522.h"  // 包含RC522驱动的头文件

// PcdRequest函数:寻找卡片
// req_code: 寻卡方式。0x52为寻找感应区内所有符合14443A标准的卡,0x26为寻找未进入休眠状态的卡
// pTagType: 输出卡片类型代码
char PcdRequest(unsigned char req_code, unsigned char *pTagType)
{
    /* 省略了一些初始化和设定的代码 */
    // 向卡片发送寻卡命令
    ucComMF522Buf[0] = req_code;
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
    /* 省略了一些处理的代码 */
    return status;
}

// PcdReset函数:复位RC522
char PcdReset(void)
{
    /* 省略了一些操作的代码 */
    // 发送复位命令
    WriteRawRC(CommandReg,PCD_RESETPHASE);
    /* 省略了一些设定的代码 */
    return MI_OK;
}

// PcdAntennaOff函数:关闭天线
void PcdAntennaOff(void)
{
    ClearBitMask(TxControlReg, 0x03);
}

// PcdAntennaOn函数:打开天线
void PcdAntennaOn(void)
{
    unsigned char i;
    i = ReadRawRC(TxControlReg);
    if (!(i & 0x03))
    {
        SetBitMask(TxControlReg, 0x03);
    }
}

// PcdAnticoll函数:防冲撞,获取卡片序列号
// pSnr: 输出卡片序列号,4字节
char PcdAnticoll(unsigned char *pSnr)
{
    /* 省略了一些初始化和设定的代码 */
    // 发送防冲撞命令
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
    /* 省略了一些处理的代码 */
    return status;
}

// ClearBitMask函数:清RC522寄存器位
// reg: 寄存器地址
// mask: 清位值
void ClearBitMask(unsigned char reg, unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}

// WriteRawRC函数:写RC522寄存器
// Address: 寄存器地址
// value: 写入的值
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    /* 省略了一些操作的代码 */
    WriteRawRC(reg,tmp | mask);  // set bit mask
}

// PcdComMF522函数:通过RC522和ISO144
/////////////////////////////////////////////////////////////////////
//功    能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr)
{
    char status; // 定义状态变量
    unsigned char i,snr_check=0; // 定义循环变量和序列号校验变量
    unsigned int  unLen; // 定义长度变量
    unsigned char ucComMF522Buf[MAXRLEN]; // 定义与MF522通信的缓冲区
 
    ClearBitMask(Status2Reg,0x08); // 清除Mifare卡的Crypto1On位
    WriteRawRC(BitFramingReg,0x00); // 清除寄存器的最后发送/接收的一些位
    ClearBitMask(CollReg,0x80); // 清除防碰撞位
 
    ucComMF522Buf[0] = PICC_ANTICOLL1; // 防冲撞命令
    ucComMF522Buf[1] = 0x20; // 位数
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); // 通过RC522和ISO14443卡通讯
 
    if (status == MI_OK) // 如果通讯成功
    {
         for (i=0; i<4; i++) // 对于序列号的每一位
         {   
             *(pSnr+i)  = ucComMF522Buf[i]; // 将通信缓冲区中的数据读取出来
             snr_check ^= ucComMF522Buf[i]; // 执行异或操作,用于后面的校验
 
         }
         if (snr_check != ucComMF522Buf[i]) // 如果校验失败
         {   status = MI_ERR;    } // 设置状态为错误
    }
    
    SetBitMask(CollReg,0x80); // 设置防碰撞位
    return status; // 返回状态
}
 
/////////////////////////////////////////////////////////////////////
//功    能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0; // 定义临时变量
    tmp = ReadRawRC(reg); // 读取寄存器的值
    WriteRawRC(reg, tmp & ~mask);  // 清除对应位的掩码
}
 
/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char i, ucAddr; // 定义循环变量和地址变量
 
    MF522_SCK = 0; // 将时钟线设置为低
    MF522_NSS = 0; // 将片选线设置为低
    ucAddr = ((Address<<1)&0x7E);
    for (i=8; i>0; i--) // 对于每一个位
    {
        if (ucAddr & 0x80) // 如果最高位为1
            MF522_MOSI = 1; // 将MOSI设置为高
        else
            MF522_MOSI = 0; // 否则将MOSI设置为低
        MF522_SCK = 1; // 将时钟线设置为高
        ucAddr <<= 1; // 将地址左移一位
        MF522_SCK = 0; // 将时钟线设置为低
    }
 
    for (i=8; i>0; i--) // 对于每一个位
    {
        if (value & 0x80) // 如果最高位为1
            MF522_MOSI = 1; // 将MOSI设置为高
        else
            MF522_MOSI = 0; // 否则将MOSI设置为低
        MF522_SCK = 1; // 将时钟线设置为高
        value <<= 1; // 将值左移一位
        MF522_SCK = 0; // 将时钟线设置为低
    }
 
    MF522_NSS = 1; // 将片选线设置为高
}
 
/////////////////////////////////////////////////////////////////////
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
    unsigned char i, ucAddr;
    unsigned char ucResult=0;
 
    MF522_SCK = 0;
    MF522_NSS = 0;
    ucAddr = ((Address<<1)&0x7E)|0x80;
 
    for (i=8; i>0; i--) // 对于每一个位
    {
        if (ucAddr & 0x80) // 如果最高位为1
            MF522_MOSI = 1; // 将MOSI设置为高
        else
            MF522_MOSI = 0; // 否则将MOSI设置为低
        MF522_SCK = 1; // 将时钟线设置为高
        ucAddr <<= 1; // 将地址左移一位
        MF522_SCK = 0; // 将时钟线设置为低
    }
 
    for (i=8; i>0; i--) // 对于每一个位
    {
        MF522_SCK = 1; // 将时钟线设置为高
        if (MF522_MISO) // 如果MISO为高
            ucResult |= 0x80; // 将结果的最高位设置为1
        MF522_SCK = 0; // 将时钟线设置为低
        if (i != 1) // 如果不是最后一个位
            ucResult <<= 1; // 将结果左移一位
    }
 
    MF522_NSS = 1; // 将片选线设置为高
 
    return ucResult; // 返回结果
}


WriteRawRC流程图

img


ReadRawRC流程图

img

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
该代码为RC522射频芯片的C语言驱动代码。以下是每个函数的详细注释和流程图:

  1. PcdRequest函数

功能:寻卡

参数说明:

req_code[IN]:寻卡方式

0x52 = 寻感应区内所有符合14443A标准的卡

0x26 = 寻未进入休眠状态的卡

pTagType[OUT]:卡片类型代码

0x4400 = Mifare_UltraLight

0x0400 = Mifare_One(S50)

0x0200 = Mifare_One(S70)

0x0800 = Mifare_Pro(X)

0x4403 = Mifare_DESFire

返回值: 成功返回MI_OK

PcdRequest函数的流程图如下:

image-20210829115928145

  1. PcdReset函数

功能:复位RC522

返回值: 成功返回MI_OK

PcdReset函数的流程图如下:

image-20210829120000015

  1. PcdAntennaOff函数

功能:关闭天线

无参数和返回值

PcdAntennaOff函数的流程图如下:

image-20210829120101760

  1. PcdAntennaOn函数

功能:开启天线

无参数和返回值

PcdAntennaOn函数的流程图如下:

image-20210829120709162

  1. PcdAnticoll函数

功能:防冲突

参数说明:

pSnr[OUT]:卡片序列号,4字节

返回值: 成功返回MI_OK

PcdAnticoll函数的流程图如下:

image-20210829121312938

  1. ClearBitMask函数

功能:清RC522寄存器位

参数说明:

reg[IN]:寄存器地址

mask[IN]:清位值

无返回值

ClearBitMask函数的流程图如下:

image-20210829124531694

  1. WriteRawRC函数

功能:写RC522寄存器

参数说明:

Address[IN]:寄存器地址

value[IN]:写入的值

无返回值

WriteRawRC函数的流程图如下:

image-20210829125222278

  1. SetBitMask函数

功能:置RC522寄存器位

参数说明:

reg[IN]:寄存器地址

mask[IN]:置位值

无返回值

SetBitMask函数的流程图如下:

image-20210829125731680

  1. PcdComMF522函数

功能:通过RC522和ISO14443卡通讯

参数说明:

Command[IN]:RC522命令字

pInData[IN]:通过RC522发送到卡片的数据

InLenByte[IN]:发送数据的字节长度

pOutData[OUT]:接收到的卡片返回数据

*pOutLenBit[OUT]:返回数据的位长度

返回值: 成功返回MI_OK

PcdComMF522函数的流程图如下:

image-20210829130146063

  1. ReadRawRC函数

功能:读RC632寄存器

参数说明:Address[IN]:寄存器地址

返回值:读出的值

ReadRawRC函数的流程图如下:

image-20210829131208031

  1. ReadICcode函数

功能:读取IC卡号

参数说明:g_ucTempbuf[0]-[3]

返回值:0代表成功,1代表失败

ReadICcode函数的流程图如下:

![image-20210829132237499](https://gitee.com/ffzs/picture_go/

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7672555
  • 你也可以参考下这篇文章:如何在C代码中使用内联汇编之明确的寄存器变量
  • 除此之外, 这篇博客: 通讯录小项目完整版【C语言基础版】中的 ※※※大家好!我是同学〖森〗,一名计算机爱好者,今天让我们进入练习模式。若有错误,请多多指教。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 👍 点赞  收藏 📝留言 都是我创作的最大的动力!

    d8c32ec9841c446887a2a80fda6e3357-00005.jpg?auth_key=1650029107-f88065807772438ea5394175321adfff-0-982a750e240773a4ab4262a2960586d8

    通讯录

  • 您还可以看一下 CSDN讲师老师的C语言精髓之编译过程视频教程课程中的 计算机的组成部分,栈内存的特点;画出内存图,引入指针的概念小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    由于题目并没有给出具体的问题,我们将以参考资料中的内容为例,提供一份优化后的C语言代码注释和流程图。

    代码注释:

    / 这段代码定义了三个函数: cal_sum:计算两个数的和 cal_sub:计算两个数的差 cal_mul:计算两个数的积 /

    include

    // 函数指针,可以指向任意一个具有相同类型和返回值的函数 typedef int (*func_ptr_t)(int, int);

    int cal_sum(int a, int b){ return a + b; }

    int cal_sub(int a, int b){ return a - b; }

    int cal_mul(int a, int b){ return a * b; }

    void calc(func_ptr_t func_ptr, int a, int b){ int res = func_ptr(a, b); printf("Result: %d\n", res); }

    int main(){ int a = 5, b = 3;

    calc(cal_sum, a, b); // 调用cal_sum函数
    calc(cal_sub, a, b); // 调用cal_sub函数
    calc(cal_mul, a, b); // 调用cal_mul函数
    
    return 0;
    

    }

    代码流程图:

    st=>start: main函数
    e=>end: 返回0
    op1=>operation: 定义函数指针类型
    op2=>operation: 定义三个计算函数
    op3=>operation: 定义calc函数,接收函数指针和两个参数
    op4=>operation: 计算结果
    op5=>operation: 打印结果
    op6=>operation: 调用calc函数,传入函数指针和两个参数
    cond1=>condition: 是否所有的计算都已经完成
    
    st->op1->op2->op3->op4->op5->cond1
    cond1(no)->op6
    cond1(yes)->e