打印
[STM32F0]

STM32的IO模拟I2C主机,硬件I2C从机,主机通讯是加入了10ms延时

[复制链接]
1769|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
woshi520laoxie|  楼主 | 2017-3-14 15:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
经过修改主机和从机已经正常通讯了,但是软件主机有好几个地方增加了延时,如果不加入延时,会导致通讯不正常。延时时间非常的长,达到了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");
        }
}
沙发
wahahaheihei| | 2017-3-14 19:42 | 只看该作者
死机是不是总线忙,你可以检测总线不忙就继续,不用固定延时,加个white判断。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

5

帖子

0

粉丝