2017-01-14 2 views
0

모바일에서 uint8 배열을 사용하여 255보다 큰 정수를 블루투스를 통해 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); 

내 장치 특정 코드 : UINT8 이후

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 
} 

단지 내가 그보다 더 큰 값을 보내 어떻게, 255 개까지의 정수를 허용?

+3

어쨌든 메모리에있는 것처럼 여러 바이트로 분할합니다. –

+0

코드가 '555'를 인쇄하지 못하고 있지만 이미 할당하지 못했습니다. – alk

답변

0

분할해야합니다. Int16에 16 비트가 있다는 것을 이미 알고 있습니다 (또는 그렇게해야합니다). 그래서 16 비트가 저장됩니다.

엔디안 니스에 대한 아주 작은 소구. 엔디안을 사용하면 저장할 때의 바이트 순서를 의미합니다. 예를 들어 값이 0x1234 인 경우 0x12 0x34 (빅 엔디안) 또는 0x34 0x12 (리틀 엔디안)로 저장할 수 있습니다.

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)); 

이 큰 엔디안 형식으로 전송 : 일반적으로 C에서

난 당신이 사용하는 어떤 언어 알고, 그래서하지 않습니다 ... 당신은 같은 것을 할 ++. 당신이 리틀 엔디안을 선호하는 경우, 더 간단한 버전이 전송의 엔디안을 알고 첫 번째 경우

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)); 

될 수

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

쓰기 (이 방법을 코드에 따라 작은 또는 큰), 두 번째로 아키텍처 및/또는 컴파일러에 따라 다릅니다.

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과 일치해야합니다.

endianness mismatch가 있으면 "임의"숫자라고 생각되는 것을 받게됩니다. 정말 쉽게 디버깅됩니다.예를 들어 값 156 (16 진수 0x9C)을 보내고 39936 (16 진수 0x9C00)을받습니다. 만나다? 바이트가 반전됩니다. 또 다른 예 : 8942 (16 진수 0x22EE)를 보내고 60962 (16 진수 0xEE22)를받는 중입니다.

끝내기 위해, 때때로 당신은 "한 블록 안에"바이트를받지 않을 것이기 때문에 당신은 이것에 문제가있을 것이라고 생각합니다. 예를 들어 1 123 555 (16 진수로, 빅 엔디안은 6 바이트, 특히 00 01 00 7B 02 2B)를 전송하면 3 또는 4 바이트로 SimbleeBLE_onReceive를 호출 한 다음 다른 사람. 따라서 패킷의 시작 및/또는 끝을 표시하는 일종의 프로토콜을 정의하고 바이트를 모두 처리 할 준비가 될 때까지 버퍼에 축적해야합니다.

+0

해설 해 주셔서 감사합니다! – MANnDAaR

0

0-255 범위 내로 유지하려면 송신 및 수신 단에서 데이터의 크기 조정 형식을 사용하십시오. 예를 들어 나누고 곱하기 때문에 데이터가 255 미만으로 전송 된 다음 수신 측에서 확장 할 수 있습니다.

데이터의 하이 및 로우 범위를 아는 경우 다른 방법은 Arduino 매핑 기능을 사용하는 것입니다. 당신은 전체 범위를 알 수없는 경우

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

, 당신은 constrain() 기능을 사용할 수 있습니다.

관련 문제