Parcourir la source

Initial Commit

Wu Han il y a 6 ans
commit
99f018f775
10 fichiers modifiés avec 756 ajouts et 0 suppressions
  1. 53 0
      .gitignore
  2. 35 0
      README.md
  3. 21 0
      SConscript
  4. BIN
      docs/i2c.gif
  5. BIN
      docs/sw_i2c.gif
  6. 281 0
      src/SoftwareI2C.cpp
  7. 79 0
      src/SoftwareI2C.h
  8. 86 0
      src/i2c_tools.cpp
  9. 153 0
      src/i2c_utils.cpp
  10. 48 0
      src/i2c_utils.h

+ 53 - 0
.gitignore

@@ -0,0 +1,53 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+.vscode/

+ 35 - 0
README.md

@@ -0,0 +1,35 @@
+# i2c-tools
+
+## 1、介绍
+
+i2c-tools 包含了一些很方便对 i2c 设备进行调试的小工具。
+
+硬件 I2C (可以 list_device 查看 i2c 设备):
+
+	---------------
+	i2c tools help:
+	---------------
+	i2c scan  bus_name
+	i2c read  bus_name address  register  [len=1]
+	i2c write bus_name address [register] data_0 data_1 ...
+
+
+![](docs/i2c.gif)
+
+软件 I2C (可以自定义两个引脚作为 SCL 和 SDA):
+
+---------------
+	i2c tools help:
+	---------------
+	i2c scan  pin_sda pin_scl
+	i2c read  pin_sda pin_scl address  register  [len=1]
+	i2c write pin_sda pin_scl address [register] data_0 data_1 ...
+	
+
+![](docs/sw_i2c.gif)
+
+## 2、联系方式
+
+* 维护:Wu Han
+* 主页:http://wuhanstudio.cc
+* 邮箱:wuhanstudio@hust.edu.cn

+ 21 - 0
SConscript

@@ -0,0 +1,21 @@
+from building import *
+import rtconfig
+
+# get current directory
+cwd     = GetCurrentDir()
+# The set of source files associated with this SConscript file.
+src     = Glob('src/*.c')
+src     = Glob('src/i2c_utils.cpp')
+src     = Glob('src/i2c_tools.cpp')
+
+if GetDepend('I2C_TOOLS_USE_SW_I2C'):
+	src    += Glob('src/SoftwareI2C.cpp')
+
+path    = [cwd + '/']
+path   += [cwd + '/src']
+
+LOCAL_CCFLAGS = ''
+
+group = DefineGroup('i2c-tools', src, depend = ['PKG_USING_I2C_TOOLS'], CPPPATH = path, LOCAL_CCFLAGS = LOCAL_CCFLAGS)
+
+Return('group')

BIN
docs/i2c.gif


BIN
docs/sw_i2c.gif


+ 281 - 0
src/SoftwareI2C.cpp

@@ -0,0 +1,281 @@
+/*
+  SoftwareI2C.cpp
+  2012 Copyright (c) Seeed Technology Inc.  All right reserved.
+
+  Author:Loovee
+  Author:Loovee
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "SoftwareI2C.h"
+
+
+/*************************************************************************************************
+ * Function Name: micros
+ * Description:  get system uptime in microseconds
+ * Parameters: none
+ * Return: microseconds
+*************************************************************************************************/
+unsigned long SoftwareI2C::micros()
+{
+    return ((unsigned long)rt_tick_get() / RT_TICK_PER_SECOND * 1000 * 1000);
+}
+
+/*************************************************************************************************
+ * Function Name: begin
+ * Description:  config IO
+ * Parameters: Sda: Scl:
+ * Return: none
+*************************************************************************************************/
+void SoftwareI2C::begin(int Sda, int Scl)
+{
+    pinSda = Sda;
+    pinScl = Scl;
+
+    rt_pin_mode(pinScl, PIN_MODE_OUTPUT);
+    rt_pin_mode(pinSda, PIN_MODE_OUTPUT);
+    sda_in_out = PIN_MODE_OUTPUT;
+    rt_pin_write(pinScl, HIGH);
+    rt_pin_write(pinSda, HIGH);
+}
+
+/*************************************************************************************************
+ * Function Name: sdaSet
+ * Description:  set sda
+ * Parameters: ucDta: HIGH or LOW
+ * Return: none
+*************************************************************************************************/
+void SoftwareI2C::sdaSet(rt_uint8_t ucDta)
+{
+
+    if(sda_in_out != PIN_MODE_OUTPUT)
+    {
+        sda_in_out = PIN_MODE_OUTPUT;
+        rt_pin_mode(pinSda, PIN_MODE_OUTPUT);
+    }
+    rt_pin_write(pinSda, ucDta);
+}
+
+/*************************************************************************************************
+ * Function Name: sclSet
+ * Description:  set scl
+ * Parameters: ucDta: HIGH or LOW
+ * Return: none
+*************************************************************************************************/
+void SoftwareI2C::sclSet(rt_uint8_t ucDta)
+{
+    rt_pin_write(pinScl, ucDta);
+}
+
+/*************************************************************************************************
+ * Function Name: getAck
+ * Description:  get ack
+ * Parameters: None
+ * Return: 0 – Nak; 1 – Ack
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::getAck(void)
+{
+    sclSet(LOW); 
+    rt_pin_mode(pinSda, PIN_MODE_INPUT_PULLUP);
+    sda_in_out = PIN_MODE_INPUT_PULLUP;
+
+    sclSet(HIGH);
+    unsigned long timer_t = micros();
+    while(1)
+    {
+        if(!rt_pin_read(pinSda))        // get ack
+        {
+            return GETACK;
+        }
+
+        if(micros() - timer_t > 100)return GETNAK;
+    }
+}
+
+/*************************************************************************************************
+ * Function Name: sendStart
+ * Description:   send start clock
+ * Parameters: None
+ * Return: None
+*************************************************************************************************/
+void SoftwareI2C::sendStart(void)
+{
+    sdaSet(LOW);
+}
+
+/*************************************************************************************************
+ * Function Name: setClockDivider
+ * Description:  setup clock divider for spi bus
+ * Parameters: divider – clock divider
+ * Return: 0 – setup ok; 1 – setup failed
+*************************************************************************************************/
+void SoftwareI2C::sendStop(void)
+{
+    sclSet(LOW);
+    sdaSet(LOW);
+    sclSet(HIGH);
+    sdaSet(HIGH);
+}
+
+/*************************************************************************************************
+ * Function Name: sendByte
+ * Description:  send a byte
+ * Parameters: ucDta: data to send
+ * Return: None
+*************************************************************************************************/
+void SoftwareI2C::sendByte(rt_uint8_t ucDta)
+{
+    for(int i=0; i<8; i++)
+    {
+        sclSet(LOW);
+        sdaSet((ucDta&0x80)!=0);
+        ucDta <<= 0;
+        sclSet(HIGH);
+        sdaSet((ucDta&0x80)!=0);
+        ucDta <<= 1;
+    }
+}
+
+/*************************************************************************************************
+ * Function Name: sendByteAck
+ * Description:  send a byte and get ack signal
+ * Parameters: ucDta: data to send
+ * Return: 0: get nak  1: get ack
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::sendByteAck(rt_uint8_t ucDta)
+{
+    sendByte(ucDta);
+    return getAck();
+}
+
+/*************************************************************************************************
+ * Function Name: beginTransmission
+ * Description:  send begin signal
+ * Parameters: divider – clock divider
+ * Return: 0: get nak  1: get ack
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::beginTransmission(rt_uint8_t addr)
+{
+    sendStart();                            // start signal
+    rt_uint8_t ret = sendByteAck(addr<<1);       // send write address and get ack
+    //sclSet(LOW);
+    return ret;
+}
+
+/*************************************************************************************************
+ * Function Name: endTransmission
+ * Description:  send stop signal
+ * Parameters: None
+ * Return: None
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::endTransmission()
+{
+    sendStop();
+    return 0;
+}
+
+/*************************************************************************************************
+ * Function Name: write
+ * Description:  send a byte
+ * Parameters: dta: data to send
+ * Return: 0: get nak  1: get ack
+*************************************************************************************************/  
+rt_uint8_t SoftwareI2C::write(rt_uint8_t dta)
+{
+    return sendByteAck(dta);
+}
+
+/*************************************************************************************************
+ * Function Name: write
+ * Description:  write array
+ * Parameters: len - length of the array
+               *dta - array to be sent
+ * Return: 0: get nak  1: get ack
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::write(rt_uint8_t *dta, rt_uint8_t len)
+{
+    for(int i=0; i<len; i++)
+    {
+    
+        if(GETACK != write(dta[i]))
+        {
+            return GETNAK;
+        }
+    }
+    
+    return GETACK;
+}
+
+/*************************************************************************************************
+ * Function Name: requestFrom
+ * Description:  request data from slave
+ * Parameters: addr - address of slave
+               len  - length of request
+ * Return: 0: get nak  1: get ack
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::requestFrom(rt_uint8_t addr, rt_uint8_t len)
+{
+    sendStart();                                // start signal
+    recv_len = len;
+    rt_uint8_t ret = sendByteAck((addr<<1)+1);       // send write address and get ack
+    //sclSet(LOW);
+    return ret;
+}
+
+/*************************************************************************************************
+ * Function Name: read
+ * Description:  read a byte from i2c
+ * Parameters: None
+ * Return: data get
+*************************************************************************************************/
+rt_uint8_t SoftwareI2C::read()
+{
+    if(!recv_len)return 0;
+
+    rt_uint8_t ucRt = 0;
+
+    rt_pin_mode(pinSda, PIN_MODE_INPUT_PULLUP);
+    sda_in_out = PIN_MODE_INPUT_PULLUP;
+    
+    for(int i=0; i<8; i++)
+    {
+        unsigned  char  ucBit;
+        sclSet(LOW);
+        sclSet(HIGH);
+        ucBit = rt_pin_read(pinSda);
+        ucRt = (ucRt << 1) + ucBit;
+    }
+
+    rt_uint8_t dta = ucRt;
+    recv_len--;
+
+    if(recv_len>0)          // send ACK
+    {
+        sclSet(LOW);                                                // sclSet(HIGH)
+        sdaSet(LOW);                                                // sdaSet(LOW)
+        sclSet(HIGH);                                               // sclSet(LOW)
+        sclSet(LOW);
+    }
+    else                    // send NAK
+    {
+        sclSet(LOW);                                                // sclSet(HIGH)
+        sdaSet(HIGH);                                               // sdaSet(LOW)
+        sclSet(HIGH);                                               // sclSet(LOW) 
+        sclSet(LOW);
+        sendStop();
+    }
+    return dta;
+}

+ 79 - 0
src/SoftwareI2C.h

@@ -0,0 +1,79 @@
+/*
+  SoftwareI2C.h
+  2012 Copyright (c) Seeed Technology Inc.  All right reserved.
+
+  Author:Loovee
+  2013-11-1
+
+  This is a Software I2C Library, can act as I2c master mode.
+  
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SOFTWAREI2C_H_
+#define _SOFTWAREI2C_H_
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define  GETACK             1       // get ack
+#define  GETNAK             0       // get nak
+   
+#ifndef  HIGH
+    #define  HIGH           1
+#endif
+#ifndef  LOW
+    #define  LOW            0
+#endif
+
+class SoftwareI2C
+{
+private:
+
+    int pinSda;
+    int pinScl;
+
+    int recv_len;
+
+    int sda_in_out;
+
+private:
+
+    inline void sdaSet(rt_uint8_t ucDta); 
+    inline void sclSet(rt_uint8_t ucDta);
+
+    inline void sendStart(void);
+    inline void sendStop(void);
+    inline void sendByte(rt_uint8_t ucDta);
+    inline rt_uint8_t getAck(void);
+    inline rt_uint8_t sendByteAck(rt_uint8_t ucDta);    // send byte and get ack
+
+    inline unsigned long micros();
+
+public:
+
+    void begin(int Sda, int Scl); 
+    rt_uint8_t beginTransmission(rt_uint8_t addr);
+    rt_uint8_t endTransmission();
+
+    rt_uint8_t write(rt_uint8_t dta);
+    rt_uint8_t write(rt_uint8_t *dta, rt_uint8_t len);
+    rt_uint8_t read();
+    rt_uint8_t requestFrom(rt_uint8_t addr, rt_uint8_t len);
+    rt_uint8_t available(){return recv_len;}
+};
+
+#endif

+ 86 - 0
src/i2c_tools.cpp

@@ -0,0 +1,86 @@
+#include "i2c_utils.h"
+
+static void i2c(int argc,char *argv[])
+{
+    if(argc > 2)
+    {
+        #ifdef I2C_TOOLS_USE_SW_I2C
+            if( i2c_init( strtonum(argv[ARG_SDA_POS]), strtonum(argv[ARG_SCL_POS])) )
+            {
+                rt_kprintf("[i2c] failed to find bus with sda=%s scl=%s\n", argv[ARG_SDA_POS], argv[ARG_SCL_POS]);
+                return;
+            }
+        #else
+            if(i2c_init(argv[ARG_BUS_NAME_POS]))
+            {
+                rt_kprintf("[i2c] failed to find bus %s\n", argv[ARG_BUS_NAME_POS]);
+                return;
+            }
+        #endif
+
+        if(!strcmp(argv[ARG_CMD_POS], "scan"))
+        {
+            i2c_scan();
+            return;
+        }
+
+        if(argc < 5)
+        {
+            i2c_help();
+            return;
+        }
+
+        if(!strcmp(argv[1], "read"))
+        {
+            rt_uint8_t buffer[I2C_TOOLS_BUFFER_SIZE];
+            rt_uint8_t len = 1;
+            if( argc == ARG_READ_MAX)
+            {
+                len = atoi(argv[ARG_READ_MAX - 1]);
+            }
+            if(i2c_read(strtonum(argv[ARG_ADDR_POS]), strtonum(argv[ARG_DATA_POS]), buffer, len) == len)
+            {
+                rt_kprintf("[ ");
+                for(rt_uint8_t i = 0; i < len; i++)
+                {
+                    rt_kprintf("0x%02X", buffer[i]);
+                    if(i != (len-1))
+                    {
+                        rt_kprintf(", ");
+                    }
+                }
+                rt_kprintf(" ]\n");
+            }
+            else
+            {
+                #ifdef I2C_TOOLS_USE_SW_I2C
+                    rt_kprintf("[i2c] read from bus failed with sda=%s scl=%s\n", argv[ARG_SDA_POS], argv[ARG_SCL_POS]);
+                #else
+                    rt_kprintf("[i2c] read from %s failed\n", argv[ARG_BUS_NAME_POS]);
+                #endif
+            }
+        }
+
+        else if(!strcmp(argv[1], "write"))
+        {
+            unsigned char buffer[I2C_TOOLS_BUFFER_SIZE];
+            for(int i=0; i<(argc-ARG_DATA_POS); i++)
+            {
+                buffer[i] = strtonum(argv[i+ARG_DATA_POS]);
+            }
+            if(!i2c_write(strtonum(argv[ARG_DATA_POS-1]), buffer, argc-ARG_DATA_POS))
+            {
+                #ifdef I2C_TOOLS_USE_SW_I2C
+                    rt_kprintf("[i2c] write to bus failed with sda=%s scl=%s\n", argv[ARG_SDA_POS], argv[ARG_SCL_POS]);
+                #else
+                    rt_kprintf("[i2c] write to %s failed\n", argv[ARG_BUS_NAME_POS]);
+                #endif
+            }
+        }
+    }
+    else
+    {
+        i2c_help();
+    }
+}
+MSH_CMD_EXPORT(i2c, i2c tools);

+ 153 - 0
src/i2c_utils.cpp

@@ -0,0 +1,153 @@
+#include "i2c_utils.h"
+
+#ifdef I2C_TOOLS_USE_SW_I2C
+    #include "SoftwareI2C.h"
+    SoftwareI2C softwarei2c;
+#else
+    struct rt_i2c_bus_device *i2c_bus;
+#endif
+
+long strtonum(const char* str)
+{
+    long data;
+    if (strcmp(str, "0x"))
+    {
+        data = (rt_uint8_t)strtol(str, NULL, 0);
+    }
+    else
+    {
+        data = atoi(str);
+    }
+    return data;
+}
+
+void i2c_help()
+{
+    rt_kprintf("---------------\n");
+    rt_kprintf("i2c tools help:\n");
+    rt_kprintf("---------------\n");
+#ifdef I2C_TOOLS_USE_SW_I2C
+    rt_kprintf("i2c scan  pin_sda pin_scl\n");
+    rt_kprintf("i2c read  pin_sda pin_scl address  register  [len=1]\n");
+    rt_kprintf("i2c write pin_sda pin_scl address [register] data_0 data_1 ...\n\n");
+#else
+    rt_kprintf("i2c scan  bus_name\n");
+    rt_kprintf("i2c read  bus_name address  register  [len=1]\n");
+    rt_kprintf("i2c write bus_name address [register] data_0 data_1 ...\n\n");
+#endif
+}
+
+#ifdef I2C_TOOLS_USE_SW_I2C
+rt_bool_t i2c_init(int sda, int scl)
+{
+    softwarei2c.begin(sda, scl);
+    return RT_EOK;
+}
+#else
+rt_bool_t i2c_init(const char* busname)
+{
+    i2c_bus = rt_i2c_bus_device_find(busname);
+    if(i2c_bus == RT_NULL)
+    {
+        return RT_ERROR;
+    }
+    else
+    {
+        return RT_EOK;
+    }
+}
+#endif
+
+int i2c_probe(char addr)
+{
+#ifdef I2C_TOOLS_USE_SW_I2C
+    int ret = softwarei2c.beginTransmission(addr);
+    softwarei2c.endTransmission();
+    return ret;
+#else
+    unsigned char cmd[1];
+    cmd[0] = 0;
+
+    struct rt_i2c_msg msgs;
+    msgs.addr = addr;
+    msgs.flags = RT_I2C_WR;
+    msgs.buf = cmd;
+    msgs.len = 0;
+
+    return rt_i2c_transfer(i2c_bus, &msgs, 1);
+#endif
+}
+
+rt_bool_t i2c_write(char addr, rt_uint8_t* data, int len)
+{
+    #ifdef I2C_TOOLS_USE_SW_I2C
+        softwarei2c.beginTransmission(addr);
+        int ret = softwarei2c.write(data, len);
+        softwarei2c.endTransmission();
+        return ret;
+    #else
+        struct rt_i2c_msg msgs;
+        msgs.addr = addr;
+        msgs.flags = RT_I2C_WR;
+        msgs.buf = data;
+        msgs.len = len;
+        return (rt_i2c_transfer(i2c_bus, &msgs, 1) == 1);
+    #endif
+}
+
+rt_uint8_t i2c_read(rt_uint8_t addr, rt_uint8_t reg, rt_uint8_t* buffer, rt_uint8_t len)
+{
+    #ifdef I2C_TOOLS_USE_SW_I2C
+        rt_uint8_t ret = 0; 
+        softwarei2c.requestFrom(addr, len);
+        while (softwarei2c.available()) {
+            buffer[ret] = softwarei2c.read();
+            ret++;
+        }
+        return ret;
+    #else
+        struct rt_i2c_msg msgs[2];
+
+        msgs[0].addr = addr;
+        msgs[0].flags = RT_I2C_WR;
+        msgs[0].buf = &reg;
+        msgs[0].len = 1;
+
+        msgs[1].addr = addr;
+        msgs[1].flags = RT_I2C_RD;
+        msgs[1].buf = buffer;
+        msgs[1].len = len;
+
+        if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2)
+        {
+            return len;
+        }
+        else
+        {
+            return 0;
+        }
+    #endif
+}
+
+void i2c_scan()
+{
+    rt_kprintf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
+    for(unsigned char i=0; i<8; i++)
+    {
+        rt_kprintf("%d0: ", i);
+        for(unsigned char j=0; j<16; j++)
+        {
+            char addr = i*16+j;
+            if( i2c_probe(addr) == 1)
+            {
+                rt_kprintf("%02X", addr);
+            }
+            else
+            {
+                rt_kprintf("--");
+            }
+            rt_kprintf(" ");
+        }
+        rt_kprintf("\n");
+    }
+}

+ 48 - 0
src/i2c_utils.h

@@ -0,0 +1,48 @@
+#ifndef _I2C_UTILS_H_
+#define _I2C_UTILS_H_
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define I2C_TOOLS_USE_SW_I2C
+
+#ifdef I2C_TOOLS_USE_SW_I2C
+    #include "SoftwareI2C.h"
+#endif
+
+#define I2C_TOOLS_BUFFER_SIZE 64
+
+#define ARG_CMD_POS             1
+
+#ifdef I2C_TOOLS_USE_SW_I2C
+    #define ARG_SDA_POS         2
+    #define ARG_SCL_POS         3
+    #define ARG_ADDR_POS        4
+    #define ARG_DATA_POS        5
+    #define ARG_READ_MAX        7
+#else
+    #define ARG_BUS_NAME_POS    2
+    #define ARG_ADDR_POS        3
+    #define ARG_DATA_POS        4
+    #define ARG_READ_MAX        6
+#endif
+
+long strtonum(const char* str);
+
+void i2c_help();
+
+#ifdef I2C_TOOLS_USE_SW_I2C
+    rt_bool_t i2c_init(int sda, int scl);
+#else
+    rt_bool_t i2c_init(const char* busname);
+#endif
+
+int  i2c_probe(char addr);
+void i2c_scan();
+
+rt_bool_t  i2c_write(char addr, rt_uint8_t* data, int len);
+rt_uint8_t i2c_read(rt_uint8_t addr, rt_uint8_t reg, rt_uint8_t* buffer, rt_uint8_t len);
+
+#endif /*_I2C_UTILS_H_*/