期望从ACKnowledge返回数据,但它没有。这是我的协议。这是我的数据表
数据表提到:“从节点将首先发送带有MSB的字节。Byte0和byte1包含预测值。所有字节都由主节点确认。”
编辑: 源库
另外,FYI我在Arduino Fio上,但我没有继承Arduino库。
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <uart.h>
#include <i2c_master.h>
#define LED PB5
#define I2C_READ 0x5A
char buffer[1];
//char data[9];
uint16_t val = 0;
uint8_t status = 0;
void getVal()
{
if(i2c_start(I2C_READ))
{
uart_puts("Start ");
val = ((uint8_t)i2c_read_ack())<<8;
val |= i2c_read_ack();
status = ((uint8_t)i2c_read_nack());
i2c_stop();
} else
{
uart_puts("Error");
i2c_stop();
}
}
int main(void)
{
init_uart(57600);
i2c_init();
DDRB = _BV(5);
for(;;)
{
getVal();
itoa(status, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
PORTB = 0xFF;
_delay_ms(500);
PORTB = 0x00;
_delay_ms(500);
}
return 0; /* never reached */}
编辑修订本:
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <uart.h>
#include <i2c_master.h>
#define LED PB5
#define I2C_READ 0x5A
char buffer[10];
//char data[9];
uint16_t val = 0;
uint8_t status = 0;
{
if(!i2c_start(I2C_READ))
{
uart_puts("Error");
i2c_stop();
} else
{
uart_puts("Start ");
i2c_start((IAQ_ADDR << 1) + 1); //i2c_start(0xB5);
val = ((uint8_t)i2c_read_ack())<<8;
val |= i2c_read_ack();
status = ((uint8_t)i2c_read_nack());
i2c_stop();
}
}
int main(void)
{
init_uart(57600);
i2c_init();
DDRB = _BV(5);
for(;;)
{
getVal();
itoa(status, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
PORTB = 0xFF;
_delay_ms(500);
PORTB = 0x00;
_delay_ms(500);
}
return 0; /* never reached */
}发布于 2016-04-13 01:05:56
如果没有正在使用的i2c库的详细信息,很难判断,但我首先要检查的一件事是i2c_start(I2C_READ)。
数据表中提供的i2c地址是0x5a,就像您在宏中放置的那样。但是第一个字节也包含读/写标志作为最不重要的位。i2c_start()函数必须将0xb5放到总线上(即读取的(0x5a << 1) + 1 )。
如果没有i2c_start(),那么您的从设备实际上不会被寻址,因此不会被破坏。
发布于 2016-04-13 01:04:32
您的程序有未定义的行为。您已经将buffer声明为:
char buffer[1];这是一个单一字符的数组。唯一可以存储的以空结尾的字符串是空字符串(即buffer[0] == '\0'所在的位置)。但是您正在使用它将整数转换为字符串。
您需要使缓冲区足够大,以容纳您希望存储在其中的最大字符串,包括终止符。
发布于 2016-04-13 01:27:37
我不知道你的根本问题是什么。你有什么症状?你的UART有什么样的输出?
正如其他人所说的,您的buffer变量太小,无法作为C字符串保存任何有价值的内容。itoa (AVR libc条目)通常提供一个以空结尾的字符串,因此您至少需要对所有字符和空值都足够大。您可能遇到了溢出缓冲区的问题,在这种情况下,您应该有一个简单的解决方案。
使用uin8_t意味着您应该为最多255个表示分配足够的空间。您需要3个字符来表示整个范围,以及一个字符作为空字符。更改您的代码以读取char buffer[4];,并查看这是否改善了您所遇到的问题。
如果I2C协议实现有错误,如果没有关于错误所在的准确信息,这将很难诊断。如果您可以访问逻辑分析器,应该可以在这里提供帮助。
编辑:
我刚刚看了一下数据表,您使用连续的i2c_start(0x5A) s的i2c_read_ack()方法似乎是正确的。但是,根据您的链接协议,您可能只是在您的UART上看到“错误”,因为i2c_start()返回0以获得成功的开始事务,并且您检查if(i2c_start(I2C_READ))何时应该在getVal()中测试if(! i2c_start(I2C_READ))。
您似乎也有一些基于链接uint8_t gist的不必要的i2c_master.c转换。如果这真的是一个与Arduino兼容的板,我建议只使用Arduino IDE,看看是否可以得到一个简单的I2C示例来使用传感器来证明您的访问方法。
https://stackoverflow.com/questions/36586465
复制相似问题