使用uint8数组

时间:2017-01-14 08:27:32

标签: c arduino buffer arraybuffer uint8t

我想使用uint8数组从移动设备发送大于255的整数到蓝牙的Arduino。

由于我使用的BLE模块不接受Uint16Array,我只能使用Uint8数组。

我的应用代码:

var data = new Uint8Array(3);
data[0]= 1;
data[1]= 123;
data[2]= 555;

ble.writeWithoutResponse(app.connectedPeripheral.id, SERVICE_UUID, WRITE_UUID, data.buffer, success, failure);

我的设备专用代码:

void SimbleeBLE_onReceive(char *data, int len) {
    Serial.print(data[0]); // prints 1
    Serial.print(data[1]); // prints 123
    Serial.print(data[2]); // failed to print 555
}

由于uint8只允许整数高达255,如何发送比这更大的值?

2 个答案:

答案 0 :(得分:0)

对发送端和接收端的数据使用某种形式的缩放,使其保持在0到255范围内。例如,分割和相乘,以便将数据发送到255以下,然后在接收端将其放大。

另一种方式,如果您知道数据的高低范围将使用Arduino映射函数。

y = map(mapped value, actual lo, actual hi, mapped lo, mapped hi)

如果您不了解全部范围,可以使用constrain()功能。

答案 1 :(得分:0)

你必须分开它。你已经知道(或者你应该)int16有16位(因此需要两个字节来存储它)。

现在关于字节序的非常小的题外话。对于字节序,您指的是存储时字节的顺序。例如,如果您的值为0x1234,则可以将其存储为0x12 0x34(大端)或0x34 0x12(小端)。

我不知道你使用的语言,所以...通常在C ++中你会做这样的事情:

const int datalen = 3;
uint16_t data[datalen];
data[0]= 1;
data[1]= 123;
data[2]= 555;

uint8_t sendingData[] = new uint8_t[datalen * sizeof(uint16_t)];
for (int i = 0; i < datalen; i++)
{
    sendingData[i * 2] = (data[i] >> 8) & 0xFF;
    sendingData[i * 2 + 1] = data[i] & 0xFF;
}

functionToSendData(sendingData, datalen * sizeof(uint16_t));

以大端格式发送。如果您更喜欢小端,请写

    sendingData[i * 2] = data[i] & 0xFF;
    sendingData[i * 2 + 1] = (data[i] >> 8) & 0xFF;

更简单的版本可以是

const int datalen = 3;
uint16_t data[datalen];
data[0]= 1;
data[1]= 123;
data[2]= 555;

functionToSendData((uint8_t*)data, datalen * sizeof(uint16_t));

在第一种情况下,您知道传输的字节顺序(根据您的编码方式,它很少或很大),在第二种情况下,它取决于体系结构和/或编译器。

在JavaScript中,您可以使用:

var sendingData = new Uint8Array(data.buffer)

然后发送这个新数组。积分转至this answer

当你收到它时,你将不得不做这三件事之一来转换它

// Data is big endian
void SimbleeBLE_onReceive(char *receivedData, int len) {
    uint16_t data[] = new uint16_t[len/2];

    for (int i = 0; i < len/2; i++)
        data = (((uint16_t)receivedData[i * 2]) << 8) + receivedData[i * 2 + 1];

    Serial.print(data[0]);
    Serial.print(data[1]);
    Serial.print(data[2]);
}

// Data is little endian
void SimbleeBLE_onReceive(char *receivedData, int len) {
    uint16_t data[] = new uint16_t[len/2];

    for (int i = 0; i < len/2; i++)
        data = receivedData[i * 2] + (((uint16_t)receivedData[i * 2 + 1]) << 8);

    Serial.print(data[0]);
    Serial.print(data[1]);
    Serial.print(data[2]);
}

// Trust the compiler
void SimbleeBLE_onReceive(char *receivedData, int len) {
    uint16_t *data = receivedData;

    Serial.print(data[0]);
    Serial.print(data[1]);
    Serial.print(data[2]);
}

最后一个方法最容易出错,因为你必须知道哪个字节序使用了编译器,它必须与sendong一个匹配。

如果字节顺序不匹配,您将收到您认为的&#34;随机&#34;数字。但它确实很容易调试。例如,您发送值156(十六进制0x9C),并接收39936(十六进制0x9C00)。看到?字节被反转。另一个例子:发送8942(十六进制0x22EE)和接收60962(十六进制0xEE22)。

刚刚结束,我认为你会遇到这方面的问题,因为有时你不会在一个区块中收到字节&#34;而是分开。例如,当您发送1 123 555(例如,十六进制,例如,大端,这将是六个字节,特别是00 01 00 7B 02 2B)时,您可以仅使用3或4个字节调用SimbleeBLE_onReceive,然后接收其他。因此,您必须定义一种协议来标记数据包的开始和/或结束,并将字节累积到缓冲区中,直到准备好处理它们。

相关问题