当前位置: 首页 > java >正文

rk3288 使用i2ctools调试pca9685

一、PCA9695的I2C地址

在这里插入图片描述

二、PCA9685的寄存器学习

寄存器表后续

  • 寄存器模式:MODE1、MODE2
  • 脉宽(占空比)设置寄存器:LED0_ON_L、LED0_ON_H、LED0_OFF_L、LED0_OFF_L
  • 周期(频率)设置寄存器:PRE_SCALE

1.1 Mode1寄存器

Mode1寄存器
bit7:0重启关闭,1重启开启
bit6:外部时钟设置引脚,设置时序:1.设置MODE1为SLEEP模式,会关闭内部晶振。2.同时设置MODE1的SLEEP和EXTCLK为1。只能被断电或者软件复位清零。
bit5:地址自动增加是能
bit4:设置为1时为sleep模式,设置为0时是正常模式
bit3:不管
bit2:不管
bit1:不管
bit0:不管

1.1.1 Mode1的Restart mode

如果想要在使用PWM时进入slepp模式(设置Mode1 bit4),那么当pwm周期结束时会将MODE1 bit7设置为1。

简单的通过i2c总线,重启所有之前活动的PWM通道可以使用下面的步骤:

  1. 读取MODE1寄存器
  2. 确认bit7是高电平,如果是,就把bit4清零(在睡眠模式),然后等待晶振稳定(500us)
  3. 写1到Mode1的bit7,所有的PWM通道将会被重启,RESTART位会被清除。
    注意sleep位清零必须保持500us,在写RESATRT位前

其他行为会清除RESART位:

  1. 断电
  2. I2C软件复位命令
  3. 如果MODE2 OCH位为0,写任何PWM寄存器会引起I2C-bus停止
  4. 如果MODE2 OCH位为1,写所有四个PWM寄存器在任何PWM通道。

1.2 Mode2寄存器

MODE2寄存器表
bit7~bit5:保留
bit4:输出逻辑反向
bit3:0输出修改在STOP命令,1输出修改在ACK
bit2:0开漏配置,1推挽
bit1~bit0:看不懂

1.3 LED输出和PWM控制

对LEDn_ON和LEDn_OFF寄存器可以独立控制PWM。
每个LED输出,有连个12bit寄存器,这些寄存器都是从0~4096。一个控制On的时间,一个控制OFF的时间。
有个Counter寄存器,回去对比On和Off的值,从而做出对应的输出。
这样就可以控制pwm的高低电平了,每个相位就是1/4096。

设置的例子:
例子图片
一个周期总共是4095,所以LED0On的位置在409,409=199h,所以LED0_ON_H = 1h LED0_ON_L=99h。
然后led off低电平的位置在1228,1228=4cch,所以LED0_OFF_H = 4h LED0_OFF_L = cch。

1.3 PWM frequecy PRE_SCALE

PRE_SCALE寄存器强制的硬件最小值是3,PRE_SCALE决定了输出的调制频率公式如下。
在这里插入图片描述
如果osc_clock是25MHz,输出的频率是200Hz那么就是:
在这里插入图片描述
如果PRE_SCALE是0x03h,那么最大频率是1526Hz
如果PRE_SCALE是0ffh,那么最大频率是24Hz
只有当MODE1 的sleep为设置为1时,PRE_SCALE才能被设置。

三、PCA9685的操作逻辑梳理

Example1

例子1:假设LED0输出,并且格式是((delay time)+(PWM duty cycle) <= 100%)
延迟时间(delay time) 是10%个周期,PWM工作周期是20%个周期(高电平20%, 低电平80%)
一个周期分为4096(0xFFFh)个单位,延迟时间(delay time): = 10% = 4096 * 10% = 409.6 = 401 = 0x19Ah
所以在寄存器LED0_ON_H=1H,LED0_ON_l =0x99H(因为计数是从0开始的,0x19Ah - 1 = 0x199h)
LED高电平的时间是20% = 4096*20%=819.2 = 819
LED低电平的时间的位置 是0x4CCh(410+819 - 1 = 1228)
所以LED0_OFF_H = 4h LED0_OFF_l = CCh

四、PCA9685的i2c-tools使用

参考资料:https://www.adafruit.com/product/815

4.1 参考例程

void Adafruit_PWMServoDriver::begin(void) {WIRE.begin();reset();
}void Adafruit_PWMServoDriver::reset(void) {write8(PCA9685_MODE1, 0x0);
}void Adafruit_PWMServoDriver::setPWMFreq(float freq) {//Serial.print("Attempting to set freq ");//Serial.println(freq);freq *= 0.9;  // Correct for overshoot in the frequency setting (see issue #11).float prescaleval = 25000000;prescaleval /= 4096;prescaleval /= freq;prescaleval -= 1;if (ENABLE_DEBUG_OUTPUT) {Serial.print("Estimated pre-scale: "); Serial.println(prescaleval);}uint8_t prescale = floor(prescaleval + 0.5);if (ENABLE_DEBUG_OUTPUT) {Serial.print("Final pre-scale: "); Serial.println(prescale);}uint8_t oldmode = read8(PCA9685_MODE1);uint8_t newmode = (oldmode&0x7F) | 0x10; // sleepwrite8(PCA9685_MODE1, newmode); // go to sleepwrite8(PCA9685_PRESCALE, prescale); // set the prescalerwrite8(PCA9685_MODE1, oldmode);delay(5);write8(PCA9685_MODE1, oldmode | 0xa1);  //  This sets the MODE1 register to turn on auto increment.// This is why the beginTransmission below was not working.//  Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX);
}void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) {//Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off);WIRE.beginTransmission(_i2caddr);WIRE.write(LED0_ON_L+4*num);WIRE.write(on);WIRE.write(on>>8);WIRE.write(off);WIRE.write(off>>8);WIRE.endTransmission();
}

4.2 使用i2c-tools调试PCA9685

# reset
i2cset -f -y I2CBUS CHIP-ADDRESS 0x00 0x0 b
# setPWMFreq
i2cget -f -y I2CBUS CHIP-ADDRESS 0x00 b
#get oldmode
i2cset -f -y I2CBUS CHIP-ADDRESS 0x00 ((oldmode&0x7f)|
0x10) b
# freq 
# freq *= 0.9 // prescaleval = 25000000/4096/freq; prescaleval -=1;
# uint8_t prescale = floor(prescaleval + 0.5);
i2cset -f -y I2CBUS CHIP-ADDRESS 0xFE prescale b
i2cset -f -y I2CBUS CHIP-ADDRESS 0x00 oldmode b
i2cset -f -y I2CBUS CHIP-ADDRESS 0x00 (oldmode|0xa1) b# setPWM(num on, off)
i2cset -f I2CBUS CHIP-ADDRESS LED0_ON_L+4*num on w
i2cset -f I2CBUS CHIP-ADDRESS LED0_ON_L+4*num off w

4.3 调试结果

[root@firefly-rk3288:~]# i2cdetect -y -a 40  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: 00 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
[root@firefly-rk3288:~]# i2cget -f -y 4 0x40 0x00 b
0x11
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x00 0x0 b
[root@firefly-rk3288:~]# i2cget -f -y 4 0x40 0x00 b
0x00
#所以oldmode是0x00,((oldmode&0x7f)|0x10) --> 0x10
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x00 0x10 b
[root@firefly-rk3288:~]# i2cget -f -y 4 0x40 0x00 b
0x10
# 简单一点prescale直接pdf上的值 0x30
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0xfe 0x30 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x00 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x00 0xa1 b
# setPWM(num on, off), num=0, on=0xff off=0x00
# 全高的话on=0x0000 off=0x0fff
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x06 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x07 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x08 0xff b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x09 0x0f b
# 结果是输出了1v[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x06 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x07 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x08 0x00 b
[root@firefly-rk3288:~]# i2cset -f -y 4 0x40 0x09 0x00 b
# 结果是输出了0v

不知道什么原因,最大只有1v

http://www.xdnf.cn/news/11210.html

相关文章:

  • 基于Attention的机器翻译模型,论文笔记
  • 嵌入式开发概述
  • 【转】Skyline软件介绍
  • 【miscellaneous】IP多播技术及其编程
  • 硬件项目开发 datasheet篇
  • 一些常用软件的网络端口协议分类介绍
  • mysql5.0免安装版_MySql5.0免安装版配置
  • 万维网(www)
  • free技术详解 lock_简化概念下的 lock-free 编程
  • MSN、QQ、阿里旺旺在线客服源代码
  • Android 开发环境搭建(详细)
  • windows注册表启动项
  • 格兰杰因果关系检验_分位数(Quantile)格兰杰因果关系的一致性非参数检验
  • 游戏软件提示d3dcompiler_43.dll的五个解决方法,亲测靠谱
  • 《MAC OS X 技术内幕》读书笔记第一章:MAC OS X的起源
  • layout_marginTop,layout_marginBottom
  • 安卓刷机及刷机包制作教程
  • VM虚拟机易被忽略的VMnet1 VMnet8
  • IsBackground的理解
  • MySQL中能否使用 show table status 中的表行数作为表的总行数直接使用?为什么?
  • DBC2000数据库如何安装
  • web前端常识之浏览器原理
  • axis2 客户端调用三种方式
  • 校准曲线、标准曲线和工作曲线,什么区别?
  • 太阳高度角方位角计算器_建冬暖式日光大棚,千万要选好方位角
  • 【Multisim仿真】NE555电路三角波、方波、正弦波发生器
  • 【区块链】深入剖析免费赚钱app的本质
  • DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏
  • 【中科院1区】Matlab实现遗传算法GA-RF故障诊断算法研究
  • Android开发需要学什么,极致干货