Как отправить массив неизвестного размера по I2C (от ведомого к ведущему)?
Когда я пытаюсь сделать что-то подобное, все работает.
Подчиненный:
# define DEFAULT_DATA_SIZE 256
byte DATA[DEFAULT_DATA_SIZE];
void requestEvent()
{
Wire.write( (byte*) DATA, sizeof(DATA));
}
void receiveEvent(int numBytes)
{
for (int i = 0; i < numBytes; i++) {
DATA[i] = Wire.read();
}
}
Мастер:
# define DEFAULT_DATA_SIZE 5
void writeData(byte data[], int numBytes) {
Wire.beginTransmission(I2C_SLAVE_ADDRESS);
for (int i = 0; i < numBytes; i++)
{
Wire.write(data[i]);
}
Wire.endTransmission();
}
void readData() {
byte data[DEFAULT_DATA_SIZE];
Wire.requestFrom( I2C_SLAVE_ADDRESS, DEFAULT_DATA_SIZE );
if ( Wire.available() == sizeof( data))
{
Wire.readBytes( (byte *) data, DEFAULT_DATA_SIZE);
}
Serial.print("Byte Array: ");
for (int i = 0; i < DEFAULT_DATA_SIZE; i++ ) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
}
byte data[5] = {0x1, 0x2, 0x3, 0x4, 0x5 };
void setup()
{
Wire.begin();
Serial.begin(9600);
writeData(data, sizeof(data));
delay(500);
readData();
}
void loop() {
}
Но это работает только тогда, когда мастер знает, какой длины должен быть массив. Если я задаю значение DEFAULT_DATA_SIZE не 5, а больше, то получаю набор случайных чисел.
Я попытался заставить подчиненное устройство сначала передать длину массива, а затем сам массив. Но по какой-то причине это не работает, и я также получаю случайные числа.
Подчиненный:
#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12
# define DEFAULT_DATA_SIZE 256
byte DATA[DEFAULT_DATA_SIZE];
int RECEIVED_NUMBYTES = 0;
bool isNumBytesSended = false;
void setup()
{
Wire.begin(I2C_SLAVE_ADDRESS);
delay(1000);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
}
void loop()
{
}
void requestEvent()
{
if (!isNumBytesSended) {
isNumBytesSended = true;
Wire.write(RECEIVED_NUMBYTES);
}
else {
isNumBytesSended = false;
Wire.write( (byte*) DATA, sizeof(DATA));
}
}
void receiveEvent(int numBytes)
{
RECEIVED_NUMBYTES = numBytes;
for (int i = 0; i < numBytes; i++) {
DATA[i] = Wire.read();
}
}
Мастер:
#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12
# define DEFAULT_DATA_SIZE 10
void writeData(byte data[], int numBytes) {
Wire.beginTransmission(I2C_SLAVE_ADDRESS);
for (int i = 0; i < numBytes; i++)
{
Wire.write(data[i]);
}
Wire.endTransmission();
}
void readData() {
Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
int numBytes = Wire.read();
Serial.println("numBytes: " + String(numBytes));
byte data[numBytes];
if ( Wire.available() == sizeof( data))
{
Wire.readBytes( (byte *) data, numBytes);
}
Serial.print("Byte Array: ");
for (int i = 0; i < numBytes; i++ ) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
}
byte data[5] = {0x1, 0x2, 0x3, 0x4, 0x5 };
void setup()
{
Wire.begin();
Serial.begin(9600);
writeData(data, sizeof(data));
delay(100);
readData();
}
void loop() {
}
Основные результаты:
01:20:13.844 -> numBytes: 5
01:20:13.878 -> Byte Array: 11 8 212 8 22
01:21:51.222 -> numBytes: 0
01:21:51.255 -> Byte Array:
01:21:54.323 -> numBytes: 5
01:21:54.323 -> Byte Array: 11 8 212 8 22
01:22:01.682 -> numBytes: 0
01:22:01.717 -> Byte Array:
01:22:04.280 -> numBytes: 5
01:22:04.314 -> Byte Array: 11 8 212 8 22
01:22:06.879 -> numBytes: 0
01:22:06.912 -> Byte Array:
01:22:10.386 -> numBytes: 5
01:22:10.420 -> Byte Array: 11 8 212 8 22
Подскажите, пожалуйста, как лучше всего решить эту проблему. Может, все значения передавать по одному байту, а между началом новых данных ставить специальный разделитель?
@yoloy, 👍0
Обсуждение1 ответ
да, идея отправлять по одному байту за раз и указывать длину массива сработала. Удивлен, что не сделал этого раньше :)
РАБ:
#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12
# define DEFAULT_DATA_SIZE 256
byte DATA[DEFAULT_DATA_SIZE];
int pointer = 0;
void setup()
{
Wire.begin(I2C_SLAVE_ADDRESS);
delay(1000);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
}
void loop()
{
}
void requestEvent()
{
if (pointer > DATA[0]) {
Wire.write(0);
}
else {
Wire.write(DATA[pointer++]);
}
}
void receiveEvent(int numBytes)
{
DATA[0] = numBytes;
for (int i = 1; i <= numBytes; i++) {
DATA[i] = Wire.read();
}
pointer = 0;
}
МАСТЕР:
#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12
void writeData(byte data[], int numBytes) {
Wire.beginTransmission(I2C_SLAVE_ADDRESS);
for (int i = 0; i < numBytes; i++)
{
Wire.write(data[i]);
}
Wire.endTransmission();
}
void readData() {
Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
int numBytes = Wire.read();
Serial.println("numBytes: " + String(numBytes));
byte data[numBytes];
for (int i = 0; i < numBytes; i++) {
Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
data[i] = Wire.read();
}
Serial.print("Byte Array: ");
for (int i = 0; i < numBytes; i++ ) {
Serial.print(data[i]);
Serial.print(" ");
}
Serial.println();
}
byte data[8] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
void setup()
{
Wire.begin();
Serial.begin(9600);
writeData(data, sizeof(data));
delay(100);
readData();
}
void loop() {
}
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- Как отправить строку на мастер с помощью i2c
- Как выбрать альтернативные контакты I2C на ESP32?
- Что означает в I2C «NACK получен»?
- NodeMCU с RFID RC522 и LCD-модулем интерфейса I2C вместе
- Несколько датчиков I2C с одинаковым адресом
Вы решаете проблему, отправляя сначала длину. Я бы отредактировал вопрос, включив в него этот код, который, как вы сказали, не работает, а также точные данные, которые вы отправляете, и точные данные, которые вы получили., @romkey
@romkey, добавил, @yoloy
Я получаю набор случайных чисел
... числа не случайны, потому что они повторяются... хотя числа недействительны, @jsotolaПопробуйте сделать первый байт длиной. Это удержит вас от отправки нулевого размера, но первый байт будет 0. Создайте функцию, которая будет отправлять массив байт за байтом. Ваше получение также должно знать формат., @Gil