2 일이 지나도이 작업을 시도한 후에는 문제를 해결할 수 없습니다.
그래서 저는 CAN 버스를 사용하여 가속도계 데이터와 시간 데이터를 전송하고 있습니다 (71 분 미만인 경우 micros () 함수는 부호없는 길이가 될 수있는 데이터를 출력합니다).하지만 데이터를 바이트로 전송해야합니다. 16 비트 int를 2 바이트로 비트 시프트 할 수 있었지만 해당 메서드 (나중에 추가 예정)를 long을 사용하는 데 외삽하는 데 문제가 있습니다. 내 자신의 함수를 만드는 것이 처음이므로 유니온 메서드를 이해하는 데 문제가 있습니다. 가능한 한 간단하게 해주시기 바랍니다. 🙂
댓글
- 총계에서 최대 바이트 3을 빼고 최대 바이트 2를 빼면 바이트 3을 얻을 수 있습니다. 바이트 4는 최대 바이트 4 빼기 숫자에서 최대 바이트 3 +1을 뺀 값입니다.
Answer
비트 시프 팅 및 비트 및 연산자.
다음은 추출 할 수있는 예입니다. long
변수의 개별 바이트. 길이가 다른 변수로 확장하는 것이 쉽지 않을 것 같습니다.
void loop() { long a=0x12345678, c=0; byte b[4]; Serial.println("Original:"); Serial.println(a,HEX); delay(1000); Serial.println("Individual bytes:"); for (int i=0; i<4; i++) { b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable Serial.println(b[i],HEX); delay(1000); } for (int i=0; i<4; i++) { c+=b[i]<<(i*8); } Serial.println("Reconstructed:"); Serial.println(c,HEX); delay(1000); }
어떤 바이트 순서 (빅 엔디안 또는 리틀 엔디안)가 예상되는지에 따라 전송 또는 수신 후에 바이트 순서를 변경해야합니다.
댓글
- 원칙을 매우 간단하고 이해하기 쉬우므로 감사합니다. 그러나 " 재구성 된 " 5678 만 인쇄합니까?
- 내 답변에서 코드 스 니펫을 복사 했습니까? 내 nodemcu에서 코드를 실행하면 정답을 얻습니다.
- 예, 코드를 복사하여 붙여넣고 void setup (); 및 Serial.begin (9600); 내 arduino nano에서 실행할 코드를 얻으려면
- 기본적으로 8 비트 AVR에서 같음의 오른쪽 기본값은 16 비트로 서명 된 int 산술입니다. 그래서 배열을 루프의 uint32_t로 캐스팅합니다. 이것이 가장 효율적인 방법인지 확실하지 않지만 작동합니다! 도와 주셔서 감사합니다.
- 예, 맞습니다. nodemcu에서 시도했을 때 ' arduino 컨트롤러에 대해 생각하지 않았습니다.
답변
union
유형은 struct
와 유사하지만 요소의 각 구성원이 같은 기억. struct
를 정의하여 2 개의 멤버 (4 바이트 유형 1 개와 단일 바이트 유형의 4 요소 배열 1 개)를 가지도록 정의하면 동일한 데이터를 쉽게 참조 할 수 있습니다. 전체 4 바이트 요소 또는 원하는 바이트 단위로.
union packed_long { long l; byte b[4]; };
이 유형이므로 변수를 다음과 같이 선언해야합니다. 해당 유형 :
packed_long mydata;
이제 mydata
의 두 하위 요소가 있습니다. l
및 b[]
.
long
값을 저장하려면 l
부분 :
mydata.l = myaccel.getY();
4 바이트 각각에 액세스하려면 :
byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3];
수신 측에서는 4 바이트를 각각 가져옵니다.
mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read();
같은 순서로 바이트를받는 경우 이제 mydata.l
에서 long
값에 액세스 할 수 있습니다.
다른 실제 크기 유형은 컴파일러와 아키텍처에 따라 다르므로 항상 32 비트로 작업 할 수 있도록 값을 한정된 크기의 변수로 정의 할 수도 있습니다. int32_t
(부호있는 32 비트 정수 ) 또는 uint32_t
(부호없는 32 비트 정수).
Answer
long을 보내는 방법은 마스크를 끄고 LSB 바이트 (CAN 표준)를 보낸 다음 다음 항목은 LSB 위치로, 4 바이트 :
uint32_t data; // Send to CAN bus LSB-first // This method is destructive; data should be a temp if the // Arduino is to retain the data after sending it. for( uint8_t b = 4; b > 0; --b ){ sendByte(data & 0xFF); // send curr byte data >>= 8; // shift that byte away } // Read from CAN bus for( uint8_t b = 4; b > 0; --b ){ data >>= 8; // make room for byte data |= (readByte() << 8); // read next higher byte } //
주석
- OK, CAN 표준 LSB가 먼저입니다. CAN에 대한 지식이 있으므로 8 바이트 패킷을 보내는 것으로 볼 수 있는데 그중 하나 또는 두 개만 데이터입니까? 총 16 바이트의 정보를 얻으려면 8 개의 패킷이 필요합니까?
- 잡았습니다! CAN 버스에 대해 제가 알고있는 모든 것에 대한 '는 Wikipedia 에서 가져온 것입니다. 온라인에 CAN 버스 문서가 많이 있습니다. 해당 기사 '의 참고 문헌이 좋은 시작입니다.
- 8 바이트는 표준 can-frame의 데이터 페이로드 크기입니다. 따라서 16 바이트의 정보를 전송하려면 두 개의 표준 프레임이 필요합니다. 최신 can-fd는 프레임 당 64 바이트 데이터 페이로드를 지원합니다.