经过修改主机和从机已经正常通讯了,但是软件主机有好几个地方增加了延时,如果不加入延时,会导致通讯不正常。延时时间非常的长,达到了10ms,为了防止出错延长到了13ms
有两个地方加入了延时:延时时间的位置用特殊延时进行标注。1、读写切换的时候增加了至少3ms的延时
2、数据读取结束之后增加了7ms的延时
数据是这样的,硬件从机发送的数据是对的,但是主机中读取数据的时候如果不加入延时,那么数据会读取不到
因为调用了 I2C_SendData(I2C1,MYDATA[Tx_count]); 这个函数的时候发送的数据是对的,并且DR里面的数据也是有的。但是软件主机需要较长的时间来读写
软件主机:
/* send one byte data from high bit to low bit */
static void IIC_Send_Byte(u8 txd)
{
u8 t;
SCL_L;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
//IIC_SDA=(txd&0x80)>>7;
if((txd&0x80)>>7)
SDA_H;
else
SDA_L;
txd<<=1;
I2C_delay(); //对TEA5767这三个延时都是必须的
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
}
/* receive one byte data from high bit to low bit */
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_H;
I2C_delay();
for(i=0;i<8;i++ )
{
receive<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(READ_SDA)receive++;
}
delay_ms(8); //这里至少需要7ms的时间
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
SDA_H;
return receive;
}
/
/*
*********************************************************************************************************
* 函 数 名: rfid_ReadBytes
* 功能说明: 从RFID读取若干数据
* 形 参:_usAddress : 起始地址, 【这里写0,表示读取卡的块号】
* _usSize : 数据长度,单位为字节 【这里写8,读取两个块,8个字节】
* _pReadBuf : 存放读到的数据的缓冲区指针 【读取的块号】
* 返 回 值: 0 表示失败,1表示成功
*********************************************************************************************************
*/
uint8_t rfid_ReadBytes(uint8_t *_pReadBuf,const uint16_t _usAddress,const uint16_t _usSize)
{
uint16_t i,j;
IIC_Start();
IIC_Send_Byte(RFID_ADDR | REID_W); /* 此处是写指令 */
if(TRUE != IIC_Wait_Ack())
{
goto cmd_fail; /* 器件无应答 */
}
IIC_Send_Byte((uint8_t)_usAddress);
if(TRUE != IIC_Wait_Ack())
{
goto cmd_fail; /* 器件无应答 */
}
// delay_ms(1); /* 读写切换不延时会读不到数据 */
IIC_Start();
IIC_Send_Byte(RFID_ADDR | REID_R); /* 此处是读指令 */
delay_ms(5); /* 这里至少延时3ms,否则读到的是上一次的数据 */
if(TRUE != IIC_Wait_Ack())
{
goto cmd_fail; /* 器件无应答 */
}
j = _usSize;
for (i = 0; i < j; i++)
{
if (i != _usSize - 1)
{
_pReadBuf = IIC_Read_Byte(1); /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */
}
else
{
_pReadBuf = IIC_Read_Byte(0); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
}
}
IIC_Stop();
return 1; /* 执行成功 */
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
IIC_Stop();
return 0; /* 执行失败 */
}
硬件从机:
用的是中断处理
void I2C1_IRQHandler(void)
{
u8 i;
u32 AddCode;
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE
| I2C_ISR_TXIS |I2C_ISR_TXE);
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x:",AddCode >> 16 );
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF;
printf("发送模式 ");
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF;
printf("接收模式 ");
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
return_data_cnt = I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok
}
printf("接收到数据 0x%x \r\n",return_data_cnt);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,MYDATA[Tx_count]);
printf("return_data_cnt :0x%x \r\n",Tx_count);
printf("发送的数据 DataUID[return_data_cnt]:0x%x \r\n",MYDATA[Tx_count]);
Tx_count++;
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;
Tx_count = 0;
printf("停止检查标志位 \r\n");
}
} |