2017-09-12 62 views
1

我试图用adafruit PWM伺服控制器来控制几个伺服器。它使用i2c接口从微控制器进行通信。 https://www.adafruit.com/product/815I2C与Atmega168

我正在使用Atmega 168试图使用简单的i2c库向微控制器发送I2C指令。

#include "i2c.h" 

void initI2C(void) { 
    TWBR = 32;        /* set bit rate, see p. 242 */ 
            /* 8MHz/(16+2*TWBR*1) ~= 100kHz */ 
    TWCR |= (1 << TWEN);          /* enable */ 
} 

void i2cWaitForComplete(void) { 
    loop_until_bit_is_set(TWCR, TWINT); 
} 

void i2cStart(void) { 
    TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWSTA)); 
    i2cWaitForComplete(); 
} 

void i2cStop(void) { 
    TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWSTO)); 
} 

uint8_t i2cReadAck(void) { 
    TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWEA)); 
    i2cWaitForComplete(); 
    return (TWDR); 
} 

uint8_t i2cReadNoAck(void) { 
    TWCR = (_BV(TWINT) | _BV(TWEN)); 
    i2cWaitForComplete(); 
    return (TWDR); 
} 

void i2cSend(uint16_t data) { 
    TWDR = data; 
    TWCR = (_BV(TWINT) | _BV(TWEN));     /* init and enable */ 
    i2cWaitForComplete(); 
} 

,我发现,Arduino的驱动伺服控制器的地址,但我有问题设置主板的PWM。这里是代码,我尝试使用:

#include <avr/io.h> 
#include <util/delay.h> 
#include <avr/interrupt.h> 
#include "i2c.h" 

#define SERVO_MIN 1000 
#define SERVO_MAX 2000 
#define SERVO_MID 1500 

#define PCA9685_ADDR 0x4 

#define PCA9685_MODE1 0x0 

#define LED0_ON_L 0x6 
#define LED0_ON_H 0x7 
#define LED0_OFF_L 0x8 
#define LED0_OFF_H 0x9 

int main(void) 
{ 
    initI2C(); 
    setupController(); 
    for(int i = 1; i < 17; i++) { 
    setServo(i, 0, 4026); 
    } 
    return 0; 
} 

void setupController() { 
    i2cStart(); 
    i2cSend(PCA9685_ADDR); 
    i2cSend(PCA9685_MODE1); 
    i2cSend(0x0); 
    i2cStop(); 
} 

void setServo(uint8_t id, uint16_t start, uint16_t stop) { 
    i2cStart(); 
    i2cSend(PCA9685_ADDR); 
    i2cSend(LED0_ON_L+4*id); 
    i2cSend(start); 
    i2cSend(start>>8); 
    i2cSend(stop); 
    i2cSend(stop>>8); 
    i2cStop(); 
} 

这里是驱动程序:https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library

我敢肯定我的I2C没有设置正确?有什么建议么?

谢谢! :)

+1

检查硬件透视图,SDA和SCL引脚是否被正确拉升。 –

+0

我做到了,他们是。一切都正确地连接起来。我得出结论,这是我的代码。我想我可能不会将我的命令发送到正确的寄存器? PWM地址为0x40 – user2536897

+1

在SDA和SCL引脚上使用DSO和检查信号,确保它能及时产生信号。首先做基本测试,从主设备发送从设备ID并检查从设备是否确认。 –

回答

0

您的i2c库对于atmega168是错误的。 TWI数据寄存器是一个8位寄存器,您试图向其写入一个16位值。 I2C Not working with PCA9685中的问题使用8位数据TWI(i2c)驱动程序。

i2c已正确初始化,由于默认情况下,它是在默认情况下供电并在atmega168复位时提供的,因此您无需关心。但是,如果TWI外设供电或不供电,您应该更好地检查PRR.PRTWI寄存器 - 也许您可以使用低功耗的库来关闭TWI。

此外,您没有明确保证总线上的两个字节之间的等待时间,因为你可以在这里看到:Address and 1 Byte Transfer on TWI 从属的ACK和书面总线上的下一个数据后,需要有一个空闲窗口。

因此,基本上,你错过了两个主要方面:

  1. 8位数据寄存器需要与数据的1字节不是两个字节之间由主机驱动总线上的unit16
  2. 明确空闲时间(写入你)