32 비트 길이를 4 바이트로 변환했다가 다시 되돌릴 수 있습니다. CAN 버스

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의 두 하위 요소가 있습니다. lb[].

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 바이트 데이터 페이로드를 지원합니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다