本帖最后由 er357951 于 2012-5-18 18:24 编辑
RT,之前发了个帖子,无人问津。所以无人问津这段时间里鄙人继续潜心研究,终于又遇到了一个蛋疼的问题。
关于结构体在子函数间的调用导致成员的值显示异常的问题。如下:
这是一个RC500的函数库里的一个子函数:
/////////////////////////////////////////////////////////////////////
//功 能:寻卡
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x0A= Mifare_UltraLight
// 0x04 = Mifare_One(S50)
// 0x02 = Mifare_One(S70)
// 0x08 = Mifare_Pro
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status;
struct TranSciveBuffer MfComData;
struct TranSciveBuffer *pi;
pi = &MfComData;
WriteRawRC(RegChannelRedundancy,0x03);
//无CRC,单独产生或者出现奇数的奇偶校验,
//奇偶校验位在每个字节后插入发送数据流中并会出现在接收数据流的每个字节后
ClearBitMask(RegControl,0x08);
//该位指示Crypto1 单元关闭因此与卡的所有数据通信都不被加密
WriteRawRC(RegBitFraming,0x07);
//TxLastBits 用于位方式帧的发送TxLastBits
//定义要发送的最后一个字节的位数目000指示最后字节的所有位都要发送在发送之后TxLastBits 自动清零
SetBitMask(RegTxControl,0x03);
//关闭天线
PcdSetTmo(4);
MfComData.MfCommand = PCD_TRANSCEIVE;
MfComData.MfLength=1;
MfComData.MfData[0] = req_code;
status = PcdComTransceive(pi); //①
if (!status)
{
if (MfComData.MfLength != 0x10)
{ status = MI_BITCOUNTERR; }
}
*pTagType = MfComData.MfData[0];
return status;
其中结构体struct TranSciveBuffer MfComData;在之前就声明了:
extern struct TranSciveBuffer{unsigned char MfCommand;
unsigned int MfLength;
unsigned char MfData[64];
};
然后在①处调用子程序PcdComTransceive,然后,问题来了。
PcdComTransceive源程序如下:
/////////////////////////////////////////////////////////////////////
//通过RC500和ISO14443卡通讯
//input: pi->MfCommand = RC500命令字
// pi->MfLength = 发送的数据长度
// pi->MfData[] = 发送数据
//output:status = 错误字
// pi->MfLength = 接收的数据BIT长度
// pi->MfData[] = 接收数据
/////////////////////////////////////////////////////////////////////
char PcdComTransceive(struct TranSciveBuffer *pi)
{
bit recebyte = 0;
char status;
unsigned char irqEn = 0x00;
unsigned char waitFor = 0x00;
unsigned char lastBits;
unsigned char n;
unsigned int i;
AAA=pi->MfLength; //②这一句不是源程序,是我用一个全局变量AAA取之前的结构体的成员MfLength的值,然后放到12864上显示。AAA在12864上显示没问题,这是提出问题的基础。
switch (pi->MfCommand)
{
case PCD_IDLE:
irqEn = 0x00;
waitFor = 0x00;
break;
case PCD_WRITEE2:
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_READE2:
irqEn = 0x07;
waitFor = 0x04;
recebyte=1;
break;
case PCD_LOADCONFIG:
case PCD_LOADKEYE2:
case PCD_AUTHENT1:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_CALCCRC:
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_AUTHENT2:
irqEn = 0x04;
waitFor = 0x04;
break;
case PCD_RECEIVE:
irqEn = 0x06;
waitFor = 0x04;
recebyte=1;
break;
case PCD_LOADKEY:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSMIT:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSCEIVE:
irqEn = 0x3D;
waitFor = 0x04;
recebyte=1;
break;
default:
pi->MfCommand = MI_UNKNOWN_COMMAND;
break;
}
if (pi->MfCommand != MI_UNKNOWN_COMMAND)
{
WriteRawRC(RegPage,0x00);
WriteRawRC(RegInterruptEn,0x7F);
//清除中断使能
WriteRawRC(RegInterruptRq,0x7F);
//清除中断标志
WriteRawRC(RegCommand,PCD_IDLE);
//清除Command寄存器
SetBitMask(RegControl,0x01);
//清除FIFO指针
// WriteRawRC(RegControl,0x03);
WriteRawRC(RegInterruptEn,irqEn|0x80);
for (i=0; i<1; i++)
{
WriteRawRC(RegFIFOData, pi->MfData);//将数据写入FIFO
}
// AAA=pi->MfData[0];
WriteRawRC(RegCommand, 0x52);//将指令写入Command寄存器
i = 0x4500; //
AAA=ReadRawRC(RegCommand);
do
{
n = ReadRawRC(RegInterruptRq);//当定时器TimerValue 寄存器值减为0 时置位
i--;
}
while ((i!=0) && !(n&irqEn&0x20) && !(n&waitFor));
//等待数据发送完 n&waitFor表示命令自动结束
//
AAA=ReadRawRC(RegCommand);
// AAA=ReadRawRC(RegFIFOData);
// AAA=pi->MfData[0];
//
AAA=pi->MfCommand;
status = MI_COM_ERR;
if ((i!=0) && !(n&irqEn&0x20))
//FIFO数据超限或i=0
{
if (!(ReadRawRC(RegErrorFlag)&0x17))
//没出错
{
status = MI_OK;
if (recebyte) //从PICC读数据
表示有返回数据
{
n = ReadRawRC(RegFIFOLength);//指示保存在FIFO 缓冲区的字节数
//写入FIFOData寄存器增加,读减少FIFOLength
lastBits = ReadRawRC(RegSecondaryStatus) & 0x07;
if (lastBits)//显示最后接收字节的有效位个数如果为0 整个字节有效
{
pi->MfLength = (n-1)*8 + lastBits;
}
else
{
pi->MfLength = n*8;//计算比特数长度
}
if (n == 0)
{
n = 1;
}
for (i=0; i<n; i++)
{
pi->MfData = ReadRawRC(RegFIFOData);//读出FIFO的数据
}
}
}
else if (ReadRawRC(RegErrorFlag)&0x01)//如果检测到一个位冲突该位置位该位在PrepareRx
//状态中接收器的启动阶段自动清零
{
status = MI_COLLERR;
if (recebyte)
{
n = ReadRawRC(RegFIFOLength);
lastBits = ReadRawRC(RegSecondaryStatus) & 0x07;
if (lastBits)
{
pi->MfLength = (n-1)*8 + lastBits;
}
else
{
pi->MfLength = n*8;
}
if (n == 0)
{
n = 1;
}
for (i=0; i<n; i++)
{
pi->MfData[i+1] = ReadRawRC(RegFIFOData);
}
}
pi->MfData[0]=ReadRawRC(0x0B);
}
}
else if (n & irqEn & 0x20)
{ status = MI_NOTAGERR; sond=0; }
else if (!(ReadRawRC(RegErrorFlag)&0x17))
{ status = MI_ACCESSTIMEOUT; }
else
{ status = MI_COM_ERR; }
WriteRawRC(RegInterruptEn,0x7F);
WriteRawRC(RegInterruptRq,0x7F);
SetBitMask(RegControl,0x04); // stop timer now
WriteRawRC(RegCommand,PCD_IDLE);
}
return status;
}
}
我在②处插入一个全局变量AAA(自己定义,调试用的)观察pi->MfLength的时候,pi->MfLength的值就从1变成2了,而且无论在第一个子函数PcdRequest里怎么改变MfComData.MfLength的值,到了第二个子函数PcdComTransceive以后pi->MfLength都会变成2,貌似是固定了的。。。
同样的方法,我用AAA在第一个子函数里观察就正常,到了第二个子函数就不正常,这非常诡异。
但是,用同样的方法观察,pi->MfCommand(这是结构体的第一个成员)就是正常的,第一个子函数负什么值,它在第二个子函数里都能正常显示。
今天一天,问了3个老师,C语言的老师说从C的角度,应该是没问题,叫我换一个角度考虑。其他两个老师找不出原因,鼓励我继续看程序找原因。。。。
RC500的确是一个很难搞懂的芯片,一路上遇见很多奇怪的问题。所以特地来二姨家诚心发问,希望谁做过的能帮帮我,这几天真是被这个搞得郁闷透了。。。
|