pq113_6的个人空间 https://bbs.21ic.com/?51690 [收藏] [复制] [RSS]

日志

USB桥接 - 7 USB2IIC(IO模拟)

已有 481 次阅读2018-9-18 15:48 |个人分类:USB桥接|系统分类:接口电路

上篇中的IIC程序在读写EEPROM时能正常工作,但是在读写OLED/DS1307时有问题(待查),所以才引出此篇。
1. start, stop都已经是IO方式模拟的,所以这2个函数不需要修改
2. 增加一个bool变量ioCtrl来表示是使用IO模拟还是用命令实现。当ioCtrl == true时表示使用IO模拟
3. 修改函数sendByte
        a.将命令0x13拆解为8个IO口模拟操作方式
        if (ioCtrl == true) 
         { 
                 for(byte j = 0; j < 8; j++) 
                 { 
                         state &= (byte)0xfe;                    //SCL outputs low 
                         //for (int i = 0; i < iicCLK; i++) 
                         { 
                                 ftCommand.Add((byte)0x80);
                                 ftCommand.Add(state); 
                                 ftCommand.Add(dir); 
                         }
                         if ((dat & 0x80) == 0x80) 
                                 state |= (byte)0x02;
                         else 
                                 state &= (byte)0xfd; 
                         dat <<= 1; 
                         dir |= (byte)0x02;
                         //Set SDA as output 
                         //for (int i = 0; i < iicCLK; i++) 
                         { 
                                 ftCommand.Add((byte)0x80); 
                                 ftCommand.Add(state); 
                                 ftCommand.Add(dir); 
                         } 
                         state |= (byte)0x01; 
                         //set SCL to high 
                         for (int i = 0; i < iicCLK * 1; i++) 
                         { 
                                 ftCommand.Add((byte)0x80);
                                 ftCommand.Add(state); 
                                 ftCommand.Add(dir); 
                         } 
                 } 
         }
         else 
         { 
                 state &= (byte)0xfe;
                //SCL outputs low 
                 state |= (byte)0x02; 
                 //SDA outputs high 
                 dir |= (byte)0x02; 
                 //Set SDA as output 
                 for (int i = 0; i < iicCLK; i++) 
                 { 
                         ftCommand.Add((byte)0x80);
                         ftCommand.Add(state); 
                         ftCommand.Add(dir); 
                 } 
                 ftCommand.Add((byte)0x13); 
                //Clock Data Bits Out on clock raise edge MSB first 
                 ftCommand.Add((byte)7); 
                 ftCommand.Add(dat); 
         }
        b. 修改SDA状态为输入
        state &= (byte)0xfc; 
         //state &= (byte)(0xf8); 
         dir &= (byte)0xfd;
        //Set SDA as input 
         for (int i = 0; i < iicCLK; i++) 
         { 
                 ftCommand.Add((byte)0x80); 
                 ftCommand.Add(state); 
                 ftCommand.Add(dir); 
         }
        c. 拆解0x26命令,SCL发送一个低到高的电平变化,然后读入SDA的状态。
        if (ioCtrl == true) 
         { 
                 state &= (byte)(0xfe); 
                 for (int i = 0; i < iicCLK; i++) 
                 { 
                         ftCommand.Add((byte)0x80);
                         ftCommand.Add(state); 
                         ftCommand.Add(dir); 
                 } 
                 state |= (byte)0x01;
                 //set SCL to high 
                 for (int i = 0; i < iicCLK * 10; i++) 
                 { 
                         ftCommand.Add((byte)0x80);
                         ftCommand.Add(state);
                         ftCommand.Add(dir); 
                 } 
                 ftCommand.Add((byte)0x81); 
                //Rd SDA

                state |= (byte)0x02; 
                 //SDA outputs high 
                 dir |= (byte)0x02; 
                 //Set SDA as output 
                 for (int i = 0; i < iicCLK; i++) 
                 { 
                         ftCommand.Add((byte)0x80); 
                         ftCommand.Add(state);
                         ftCommand.Add(dir); 
                 } 
         } 
         else 
         {
                 ftCommand.Add((byte)0x26); 
                //Clock Data Bits In on clock falling edge MSB first 
                 ftCommand.Add((byte)0); 
                 // 1bit
                ftCommand.Add((byte)0x87); 
         }
        d. 恢复IO的状态。
        state &= (byte)0xfe; 
         //SCL outputs low 
         //state |= (byte)0x02;
         //SDA outputs high 
         dir |= (byte)0x02;
         //Set SDA as output 
         for (int i = 0; i < iicCLK; i++)
         { 
                 ftCommand.Add((byte)0x80);
                 ftCommand.Add(state); 
                 ftCommand.Add(dir); 
         }
4. 修改write函数,在write函数里面判断ACK和NACK的判断条件有变:
 if (ioCtrl == true)
{
         if ((rdBuf[i] & 0x02) == 0x02)
         {
                 Console.WriteLine("iic write " + i + " data:" + string.Format("0x{0:x}", dat[0]) + " - return nack:" + string.Format("0x{0:x}", rdBuf[i]));
                return false;
        }
}
else
{
         if ((byte)(rdBuf[i] & 0x01) == (byte)0x01)
         {
                Console.WriteLine("iic write " + i + " data:" + string.Format("0x{0:x}", dat[0]) + " - return nack:" + string.Format("0x{0:x}", rdBuf[i]));
                return false;
         }
}
5. 修改函数receiveByte
        a.替换命令0x22
        if(ioCtrl == true) 
         { 
                 byte loop = 8; 
                 while (loop-- > 0) 
                 {
                        state &= (byte)0xfe; 
                        //SDA output low 
                         for (int i = 0; i < iicCLK; i++)
                         {
                                 ftCommand.Add((byte)0x80);
                                 ftCommand.Add(state); 
                                 ftCommand.Add(dir); 
                         }
                         state |= (byte)0x01; 
                        //SCL output high 
                         for (int i = 0; i < iicCLK; i++) 
                         { 
                                 ftCommand.Add((byte)0x80); 
                                 ftCommand.Add(state);
                                 ftCommand.Add(dir); 
                         }
                         ftCommand.Add((byte)0x81); //Rd SDA
                 } 
         }
         else 
         { 
                 ftCommand.Add((byte)0x22);
                ftCommand.Add((byte)7); 
         }
        b. 替换0x13返回ack或nack
        if (ioCtrl == true) 
         {
                 if (ack == true) 
                         state &= (byte)0xfd; 
                 else 
                         state |= (byte)0x02;
                 for (int i = 0; i < iicCLK; i++) 
                 { 
                         ftCommand.Add((byte)0x80);
                         ftCommand.Add(state);
                         ftCommand.Add(dir); 
                 } 
                 state |= (byte)0x01; 
                 for (int i = 0; i < iicCLK; i++) 
                 { 
                         ftCommand.Add((byte)0x80); 
                         ftCommand.Add(state); 
                         ftCommand.Add(dir); 
                 } 
         } 
         else 
         {
                 ftCommand.Add((byte)0x13);
                 //Clock Data Bits Out on clock raise edge MSB first
                 ftCommand.Add((byte)0x0);               // 1bit
                 if (ack == true)
                         ftCommand.Add((byte)0x00);          // SDA outputs low means ack 
                 else 
                         ftCommand.Add((byte)0x80);          // SDA outputs high means nack, only use bit7. 
         }
6. 修改函数read
        a. 由于读数据每次只能读入1bit,所以数据长度会变成8倍。
        UInt32 rdDatLen = len; 
         if (ioCtrl == true)
                 rdDatLen = len * 8;
         UInt32 rdLen = (UInt32)(addrbit / 8 + 2 + rdDatLen);
        b. 修改读取数据,因为FT232H的buffer size最大为65535,所以改成循环读取数据。
        byte[] rdBuf = new byte[rdLen]; 
         int offset = 0;
            while (true) 
         {
                 ftStatus = D2XX.FT_GetQueueStatus(ftHandle, ref byteRead); 
                 byte[] tmpBuf = new byte[byteRead]; 
                 if (ftStatus != D2XX.eDeviceStatus.FT_OK)
                 { 
                         Console.Write("iic read - get queue fail\n"); 
                         return false; 
                 } 
                 dly++; 
                 if (dly > 0xffff) 
                 {
                         Console.Write("iic read - time out\n"); 
                         return false; 
                 }
                 ftStatus = D2XX.FT_Read(ftHandle, tmpBuf, (UInt32)tmpBuf.Length, ref byteRead); 
                 if (ftStatus != D2XX.eDeviceStatus.FT_OK || byteRead != (UInt32)tmpBuf.Length) 
                 {
                         Console.Write("iic read - read data fail\n"); 
                         return false;
                 } 
                 for (int i = 0; i < tmpBuf.Length; i++ )
                 { 
                         rdBuf[offset++] = tmpBuf[i]; 
                 } 
                 if (offset >= rdLen) 
                         break;
                 Thread.Sleep(1); 
         }
        c. 判断写地址部分的ack对不对
        for (int i = 0; i < rdBuf.Length - rdDatLen; i++) 
         { 
                 //if ((rdBuf[i] & ((0x01 << i) & 0xff)) > 0)
                 if (ioCtrl == true)
                 {
                         if ((rdBuf[i] & 0x02) == 0x02) 
                         { 
                                 Console.WriteLine("iic read " + i + " data:" + string.Format("0x{0:x}", dat[0]) + " - return nack:" + string.Format("0x{0:x}", rdBuf[i])); 
                                 return false; 
                         }
                 } 
                 else 
                 { 
                         if ((byte)(rdBuf[i] & 0x01) == (byte)0x01) 
                         { 
                                 Console.WriteLine("iic read " + i + " data:" + string.Format("0x{0:x}", dat[0]) + " - return nack:" + string.Format("0x{0:x}", rdBuf[i])); 
                                 return false; 
                         } 
                 }
         }
        d. 修改获取数据的方式
        for (int i = (int)(rdBuf.Length - rdDatLen); i < rdBuf.Length; i++) 
         { 
                 if(ioCtrl == true)
                 {
                         int max = i + 8;
                         byte tmp = 0; 
                         for(; i < max; i++) 
                         { 
                                 tmp <<= 1;
                                 if ((rdBuf[i] & 0x02) == 0x02) 
                                 { 
                                         tmp |= 0x01; 
                                 } 
                         }
                        dat[(i - (rdBuf.Length - rdDatLen)) / 8 - 1] = tmp; 
                         i--; 
                 } 
                 else 
                         dat[i - (rdBuf.Length - rdDatLen)] = rdBuf[i]; 
         }

评论 (0 个评论)