2017-01-14 121 views
0

我想使用uint8數組從移動設備向Arduino發送超過藍牙的整數。使用uint8數組發送大於255的整數

由於我使用的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,我如何發送大於值?

+3

通過將其拆分爲多個字節,就像它在內存中一樣。 –

+0

該代碼不能打印'555',但未能分配。 – alk

回答

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。

如果字節順序不匹配,您會收到您認爲是「隨機」的數字。但它真的很容易調試。例如,您發送值156(十六進制0x9C),並接收39936(十六進制0x9C00)。看到?字節被反轉。另一個例子:發送8942(十六進制0x22EE)和接收60962(十六進制0xEE22)。

剛剛完成,我認爲你會遇到問題,因爲有時候你不會收到字節「在一個塊」,但分開。例如,當你發送1 123 555(以十六進制表示,例如大字節,這將是六個字節,特別是00 01 00 7B 02 2B),你可能只需要3或4字節的SimbleeBLE_onReceive調用,然後接收其他。因此,您必須定義一種協議來標記數據包的開始和/或結束,並將這些字節累積到緩衝區中,直到準備好處理它們。

+0

謝謝你的解釋性答案! – MANnDAaR

0

在發送和接收端的數據上使用某種形式的縮放來保持它在0到255的範圍內。例如分割和相乘,因此數據在255以下發送,然後在接收端進行擴展。

另一種方法是,如果您知道數據的hi和low範圍將使用Arduino映射函數。

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

如果您不知道全部範圍,可以使用constrain()函數。