Bladeren bron

update

提交该软件包的基本架构
Hao Zhu 6 jaren geleden
commit
8178aeb644
7 gewijzigde bestanden met toevoegingen van 761 en 0 verwijderingen
  1. 3 0
      .gitignore
  2. 201 0
      LICENSE
  3. 82 0
      README.md
  4. 20 0
      SConscript
  5. 280 0
      pca9685.c
  6. 112 0
      pca9685.h
  7. 63 0
      pca9685_sample.c

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+
+*.bin
+*.ipch

+ 201 - 0
LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 82 - 0
README.md

@@ -0,0 +1,82 @@
+# pca9685 软件包
+
+## 介绍
+
+`pca9685` 软件包是 RT-Thread 针对 I2C 并行口扩展电路 PCA9685T 推出的一个软件包,兼容 PCA9685A。使用这个软件包,可以在 RT-Thread 上非常方便的使用该器件,并且支持一个 I2C 总线上挂载多个 PCA9685T。
+
+本文主要介绍该软件包的使用方式、API,以及 `MSH` 测试命令。
+
+### 目录结构
+
+```
+pca9685
+│   README.md                       // 软件包说明
+│   pca9685.c                       // 源文件
+│   pca9685.h                       // 头文件
+│   pca9685_sample.c                // 软件包使用示例代码
+│   SConscript                      // RT-Thread 默认的构建脚本
+│   LICENSE                         // 许可证文件
+```
+
+### 许可证
+
+pca9685 遵循 Apache-2.0 许可,详见 `LICENSE` 文件。
+
+### 依赖
+
+- RT_Thread 3.0+
+- i2c 设备驱动
+
+## 获取方式
+
+使用 `pca9685 package` 需要在 RT-Thread 的包管理中选中它,具体路径如下:
+
+```
+RT-Thread online packages
+    peripheral libraries and drivers  --->
+        pca9685: Remote 8-bit I/O expander for I2C-bus  --->
+```
+
+进入 pca9685 软件包的配置菜单按自己的需求进行具体的配置
+
+```
+    --- pca9685: Remote 8-bit I/O expander for I2C-bus                           
+        [*]   Enable pca9685 sample
+           Version (latest)  --->
+```
+
+**Enable pca9685 sample** :开启 pca9685  使用示例
+
+配置完成后让 RT-Thread 的包管理器自动更新,或者使用 pkgs --update 命令更新包到 BSP 中。
+
+## 使用方法
+
+pca9685 软件包的使用流程一般如下:
+
+1. 初始化 pca9685 设备 `pca9685_init`
+2. 进行 PWM 的操作
+   - 使用 API `pca9685_port_read/pca9685_port_write` 同时操作 16 路 PWM
+   - 使用 API `pca9685_pin_read/pca9685_pin_write` 单独操作其中一 路 PWM
+
+详细的使用方法可以参考[pca9685 示例程序](pca9685_sample.c) 。
+
+## MSH 测试命令
+
+如果开启了 pca9685 软件包的示例程序,就会导出 `pca9685_sample` 命令到控制台。调用之后默认会在 `i2c1`总线上探测地址为 `0x80` 的 PCA9685 设备,并会操作扩展端口的第 0 口进行测试。运行结果如下:
+
+```
+msh >pca9685_sample
+[D/pca9685] pca9685 init done
+The value of pca9685.P0 is 0
+The value of pca9685.P0 is 1
+msh >
+```
+
+## 注意事项
+
+暂无。
+
+## 联系方式
+
+- 维护:[guozhanxin](https://github.com/Guozhanxin)
+- 主页:<https://github.com/RT-Thread-packages/pca9685 >

+ 20 - 0
SConscript

@@ -0,0 +1,20 @@
+from building import *
+Import('rtconfig')
+
+src   = []
+cwd   = GetCurrentDir()
+
+# add pca9685 src files.
+if GetDepend('PKG_USING_PCA9685'):
+    src += Glob('pca9685.c')
+
+if GetDepend('PKG_USING_PCA9685_SAMPLE'):
+    src += Glob('pca9685_sample.c')
+
+# add pca9685 include path.
+path  = [cwd]
+
+# add src and include to group.
+group = DefineGroup('pca9685', src, depend = ['PKG_USING_PCA9685'], CPPPATH = path)
+
+Return('group')

+ 280 - 0
pca9685.c

@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-15     greedyhao    first version
+ */
+
+#include "pca9685.h"
+
+// #define DBG_ENABLE
+#define DBG_SECTION_NAME     "pca9685"
+#define DBG_LEVEL            DBG_INFO
+#define DBG_COLOR
+#include <rtdbg.h>
+
+/**
+ * This function writes the value of the register for pca9685
+ *
+ * @param dev the pointer of device driver structure
+ * @param reg the register for pca9685
+ * @param data value to write
+ *
+ * @return the writing status, RT_EOK reprensents  writing the value of the register successfully.
+ */
+static rt_err_t write_reg(pca9685_device_t dev, rt_uint8_t reg, unsigned short length, const unsigned char *data)
+{
+    rt_int8_t res = 0;
+#ifdef RT_USING_I2C
+    struct rt_i2c_msg msgs;
+    rt_uint8_t buf[length+1];
+    buf[0] = reg;
+    int i;
+    for ( i = 1; i <= length; i++)
+    {
+        buf[i] = data[i-1];
+    }
+
+#endif
+    if (dev->bus->type == RT_Device_Class_I2CBUS)
+    {
+#ifdef RT_USING_I2C
+        msgs.addr  = dev->i2c_addr;    /* slave address */
+        msgs.flags = RT_I2C_WR;        /* write flag */
+        msgs.buf   = buf;              /* Send data pointer */
+        msgs.len   = length+1;
+
+        if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, &msgs, 1) == 1)
+        {
+            res = RT_EOK;
+        }
+        else
+        {
+            res = -RT_ERROR;
+        }
+#endif
+    }
+    else
+    {
+#ifdef RT_USING_SPI
+        res = rt_spi_send_then_send((struct rt_spi_device *)dev->bus, &reg, 1, &data, 1);
+#endif
+    }
+    return res;
+}
+
+/**
+ * This function reads the value of registers for pca9685
+ *
+ * @param dev the pointer of device driver structure
+ * @param reg the register for pca9685
+ * @param len number of register
+ * @param buf read data pointer
+ *
+ * @return the reading status, RT_EOK reprensents  reading the value of registers successfully.
+ */
+static rt_err_t read_regs(pca9685_device_t dev, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
+{
+    rt_int8_t res = 0;
+#ifdef RT_USING_I2C
+    struct rt_i2c_msg msgs[2];
+#endif
+#ifdef RT_USING_SPI
+    rt_uint8_t tmp;
+#endif
+    if (dev->bus->type == RT_Device_Class_I2CBUS)
+    {
+#ifdef RT_USING_I2C
+        msgs[0].addr  = dev->i2c_addr;    /* Slave address */
+        msgs[0].flags = RT_I2C_WR;        /* Write flag */
+        msgs[0].buf   = &reg;             /* Slave register address */
+        msgs[0].len   = 1;                /* Number of bytes sent */
+
+        msgs[1].addr  = dev->i2c_addr;    /* Slave address */
+        msgs[1].flags = RT_I2C_RD;        /* Read flag */
+        msgs[1].buf   = buf;              /* Read data pointer */
+        msgs[1].len   = len;              /* Number of bytes read */
+
+        if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, msgs, 2) == 2)
+        {
+            res = RT_EOK;
+        }
+        else
+        {
+            res = -RT_ERROR;
+        }
+#endif
+    }
+    else
+    {
+#ifdef RT_USING_SPI
+        //The first bit of the first byte contains the Read/Write bit and indicates the Read (1) or Write (0) operation.
+        tmp = reg | 0x80;
+
+        res = rt_spi_send_then_recv((struct rt_spi_device *)dev->bus, &tmp, 1, buf, len);
+#endif
+    }
+    return res;
+}
+
+/**
+ * @brief 
+ * 
+ * @param dev 
+ * @param freq 
+ */
+rt_err_t pca9685_set_pwm_freq(pca9685_device_t dev, float freq)
+{
+    rt_err_t ret = RT_EOK;
+    rt_uint8_t reg[2] = {PCA9685_MODE1};
+
+    freq *= 0.982; // Correct for overshoot in the frequency setting (see issue #11).
+    float prescaleval = 25000000;
+    prescaleval /= 4096;
+    prescaleval /= freq;
+    prescaleval -= 1;
+    rt_uint8_t prescale = (rt_uint8_t)(prescaleval + 0.5);
+    LOG_I("%d",prescale);
+
+    // rt_uint8_t prescale = 3;
+
+    rt_uint8_t oldmode = 0;
+    read_regs(dev, PCA9685_MODE1, 1, &oldmode);
+    rt_uint8_t newmode = ((oldmode & 0x7F) | 0x10);
+
+    LOG_D("sleep..");
+    ret = write_reg(dev, PCA9685_MODE1, 1, &newmode);            // go to sleep
+    if (ret != RT_EOK)
+    {
+        LOG_E("set sleep fail!");
+    }
+    read_regs(dev,PCA9685_MODE1, 1, &reg[1]);
+    LOG_I("after sleep reg:%p", reg[1]);
+
+    LOG_D("prescaler..");
+    ret = write_reg(dev, PCA9685_PRESCALE, 1, &prescale);        // set the prescaler
+    if (ret != RT_EOK)
+    {
+        LOG_E("set prescaler fail!");
+    }
+    read_regs(dev,PCA9685_MODE1, 1, &reg[1]);
+    LOG_I("after prescaler reg:%p", reg[1]);
+
+    LOG_D("old mode..");
+    ret = write_reg(dev, PCA9685_MODE1, 1, &oldmode);
+    if (ret != RT_EOK)
+    {
+        LOG_E("set oldmode fail!");
+    }
+    read_regs(dev,PCA9685_MODE1, 1, &reg[1]);
+    LOG_I("after oldmode reg:%p", reg[1]);
+
+    rt_thread_mdelay(5);
+    oldmode |= 0xA0;
+    reg[1] = oldmode;
+    LOG_D("auto run..");
+    ret = write_reg(dev, PCA9685_MODE1, 1, &oldmode); //  This sets the MODE1 register to turn on auto increment.
+
+    read_regs(dev,PCA9685_MODE1, 1, &reg[1]);
+    LOG_I("after auto reg:%p", reg[1]);
+
+    if (ret != RT_EOK)
+    {
+        LOG_E("set pwm freq fail!");
+    }
+    
+    return ret;
+}
+
+void pca9685_set_pwm(pca9685_device_t dev, rt_uint8_t num, rt_uint16_t on, rt_uint16_t off)
+{
+    rt_uint8_t outputBuffer[4] = {on, (on >> 8), off, (off >> 8)};
+    LOG_D("set pwm..");
+    write_reg(dev, LED0_ON_L + 4*num, 4, outputBuffer);
+}
+
+void pca9685_restart(pca9685_device_t dev)
+{
+    rt_uint8_t reg;
+    read_regs(dev, PCA9685_MODE1, 1, &reg);
+    if ((reg & 0x80) != 0)
+    {
+        LOG_I("restart..");
+        reg = reg & 0xBF;
+        write_reg(dev, PCA9685_MODE1, 1, &reg);
+        rt_thread_mdelay(2);
+        reg = reg | 0x80; //reset
+        write_reg(dev, PCA9685_MODE1, 1, &reg);
+    }
+    
+}
+
+pca9685_device_t pca9685_init(const char *dev_name, rt_uint8_t i2c_addr)
+{
+    rt_uint8_t buffer[] = { PCA9685_MODE1, 0x80 };
+    pca9685_device_t dev = RT_NULL;
+
+    RT_ASSERT(dev_name);
+
+    dev = rt_calloc(1, sizeof(struct pca9685_device));
+    if (dev == RT_NULL)
+    {
+        LOG_E("Can't allocate memory for pca9685 device on '%s' ", dev_name);
+        goto __exit;
+    }
+
+    dev->bus = rt_device_find(dev_name);
+    if (dev->bus == RT_NULL)
+    {
+        LOG_E("i2c_bus %s for PCA9685 not found!", dev_name);
+        goto __exit;
+    }
+
+    if (dev->bus->type == RT_Device_Class_I2CBUS)
+    {
+        if (i2c_addr != RT_NULL)
+            dev->i2c_addr = i2c_addr;
+        else
+            dev->i2c_addr = PCA9685_ADDR_DEFAULT;
+    }
+    else
+    {
+        LOG_E("Unsupported device:'%s'!", dev_name);
+        goto __exit;
+    }
+
+    LOG_D("reset..");
+    /* reset before use it */
+    if (write_reg(dev, PCA9685_MODE1, 1, &buffer[1]) != RT_EOK)
+    {
+        LOG_E("i2c_bus %s for PCA9685 opened failed!", dev_name);
+        goto __exit;
+    }
+    read_regs(dev, PCA9685_MODE1, 1, &buffer[1]);
+    LOG_I("rest mode:%p", buffer[1]);
+
+    rt_thread_mdelay(10);
+
+    pca9685_set_pwm_freq(dev, 50);
+    
+
+    LOG_D("pca9685 init done", dev_name);
+    return dev;
+
+__exit:
+    if (dev != RT_NULL)
+        rt_free(dev);
+
+    return RT_NULL;
+}
+
+void pca9685_deinit(pca9685_device_t dev)
+{
+    RT_ASSERT(dev);
+
+    rt_free(dev);
+}

+ 112 - 0
pca9685.h

@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-15     greedyhao    first version
+ */
+
+#ifndef __PCA9685_H
+#define __PCA9685_H
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define PCA9685_ADDR_DEFAULT    0x40
+
+#define PCA9685_SUBADR1         0x2 /**< i2c bus address 1 */
+#define PCA9685_SUBADR2         0x3 /**< i2c bus address 2 */
+#define PCA9685_SUBADR3         0x4 /**< i2c bus address 3 */
+
+#define PCA9685_MODE1           0x0 /**< Mode Register 1 */
+#define PCA9685_PRESCALE        0xFE /**< Prescaler for PWM output frequency */
+
+#define LED0_ON_L               0x6 /**< LED0 output and brightness control byte 0 */
+#define LED0_ON_H               0x7 /**< LED0 output and brightness control byte 1 */
+#define LED0_OFF_L              0x8 /**< LED0 output and brightness control byte 2 */
+#define LED0_OFF_H              0x9 /**< LED0 output and brightness control byte 3 */
+
+#define ALLLED_ON_L             0xFA /**< load all the LEDn_ON registers, byte 0 */
+#define ALLLED_ON_H             0xFB /**< load all the LEDn_ON registers, byte 1 */
+#define ALLLED_OFF_L            0xFC /**< load all the LEDn_OFF registers, byte 0 */
+#define ALLLED_OFF_H            0xFD /**< load all the LEDn_OFF registers, byte 1 */
+
+/* pca9685 device structure */
+struct pca9685_device
+{
+    rt_device_t bus;
+    rt_uint8_t i2c_addr;
+};
+typedef struct pca9685_device *pca9685_device_t;
+
+/**
+ * @brief 
+ * 
+ * @param dev 
+ * @param freq 
+ */
+rt_err_t pca9685_set_pwm_freq(pca9685_device_t dev, float freq);
+
+void pca9685_set_pwm(pca9685_device_t dev, rt_uint8_t num, rt_uint16_t on, rt_uint16_t off);
+
+void pca9685_restart(pca9685_device_t dev);
+
+/**
+ * This function initialize the pca9685 device.
+ *
+ * @param dev_name the name of i2c bus device
+ * @param i2c_addr the i2c device address for i2c communication,RT_NULL use default address
+ *
+ * @return the pointer of device structure, RT_NULL reprensents  initialization failed.
+ */
+pca9685_device_t pca9685_init(const char *dev_name, rt_uint8_t i2c_addr);
+
+/**
+ * This function releases memory
+ *
+ * @param dev the pointer of device structure
+ */
+void pca9685_deinit(struct pca9685_device *dev);
+
+// /**
+//  * This function read the data port of pca9685.
+//  *
+//  * @param dev the pointer of device structure
+//  *
+//  * @return the state of data port. 0xFF meas all pin is high.
+//  */
+// uint8_t pca9685_port_read(pca9685_device_t dev);
+
+// /**
+//  * This function sets the status of the data port.
+//  *
+//  * @param dev the pointer of device structure
+//  * @param port_val the port value you want to set, 0xFF meas all pin output high.
+//  */
+// void pca9685_port_write(pca9685_device_t dev, uint8_t port_val);
+
+// /**
+//  * This function read the specified port pin of the pca9685.
+//  *
+//  * @param dev the pointer of device structure
+//  * @param pin the specified pin of the data port
+//  *
+//  * @return the status of the specified data port pin, 0 is low, 1 is high.
+//  */
+// uint8_t pca9685_pin_read(pca9685_device_t dev, uint8_t pin);
+
+// /**
+//  * This function sets the status of the specified port pin.
+//  *
+//  * @param dev the pointer of device structure
+//  * @param pin_val the specified pin value you want to set, 0 is low, 1 is high.
+//  */
+// void pca9685_pin_write(pca9685_device_t dev, uint8_t pin, uint8_t pin_val);
+
+
+
+#endif
+

+ 63 - 0
pca9685_sample.c

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-15     greedyhao    first version
+ */
+
+#include <rtthread.h>
+#include "pca9685.h"
+
+// #define DBG_ENABLE
+#define DBG_SECTION_NAME     "pca9685"
+#define DBG_LEVEL            DBG_ERROR
+#define DBG_COLOR
+#include <rtdbg.h>
+
+#define I2C_BUS    "i2c3"
+
+static rt_thread_t tid1 = RT_NULL;
+
+int pca9685_sample_entry(void)
+{
+    rt_uint32_t count = 500;
+    pca9685_device_t dev = RT_NULL;
+
+    dev = pca9685_init(I2C_BUS, RT_NULL);
+
+    if (dev == RT_NULL)
+        return -1;
+
+    pca9685_set_pwm(dev, 0, 0, 306);
+    pca9685_set_pwm(dev, 1, 0, 500);
+    pca9685_set_pwm(dev, 2, 0, 1000);
+
+    while (count > 0)
+    {
+        count--;
+        rt_thread_mdelay(10);
+    }
+    
+    pca9685_deinit(dev);
+
+    return 0;
+}
+
+int pca9685_sample(void)
+{
+    tid1 = rt_thread_create("pca9685_sample",
+                            pca9685_sample_entry, RT_NULL,
+                            512, 25, 10);
+
+    if (tid1 != RT_NULL)
+        rt_thread_startup(tid1);
+
+		return 0;
+}
+#ifdef FINSH_USING_MSH
+MSH_CMD_EXPORT(pca9685_sample, a pca9685 sample);
+#endif