需要详细的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读卡器的驱动程序,主要包含以下几个函数:
此外,还包含一个ReadICcode函数,用于寻找IC卡并将卡号保存到指定缓冲区。
【大致流程图:】
【代码注释】
#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的第0、1位
}
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的第7位
return 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流程图
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
该代码为RC522射频芯片的C语言驱动代码。以下是每个函数的详细注释和流程图:
功能:寻卡
参数说明:
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函数的流程图如下:
功能:复位RC522
返回值: 成功返回MI_OK
PcdReset函数的流程图如下:
功能:关闭天线
无参数和返回值
PcdAntennaOff函数的流程图如下:
功能:开启天线
无参数和返回值
PcdAntennaOn函数的流程图如下:
功能:防冲突
参数说明:
pSnr[OUT]:卡片序列号,4字节
返回值: 成功返回MI_OK
PcdAnticoll函数的流程图如下:
功能:清RC522寄存器位
参数说明:
reg[IN]:寄存器地址
mask[IN]:清位值
无返回值
ClearBitMask函数的流程图如下:
功能:写RC522寄存器
参数说明:
Address[IN]:寄存器地址
value[IN]:写入的值
无返回值
WriteRawRC函数的流程图如下:
功能:置RC522寄存器位
参数说明:
reg[IN]:寄存器地址
mask[IN]:置位值
无返回值
SetBitMask函数的流程图如下:
功能:通过RC522和ISO14443卡通讯
参数说明:
Command[IN]:RC522命令字
pInData[IN]:通过RC522发送到卡片的数据
InLenByte[IN]:发送数据的字节长度
pOutData[OUT]:接收到的卡片返回数据
*pOutLenBit[OUT]:返回数据的位长度
返回值: 成功返回MI_OK
PcdComMF522函数的流程图如下:
功能:读RC632寄存器
参数说明:Address[IN]:寄存器地址
返回值:读出的值
ReadRawRC函数的流程图如下:
功能:读取IC卡号
参数说明:g_ucTempbuf[0]-[3]
返回值:0代表成功,1代表失败
ReadICcode函数的流程图如下:
(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