산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial Internet of Things >> 임베디드

임베디드 C 프로그래밍 언어 학습:Union Data Object 이해

포함된 C 언어의 공용체라는 데이터 개체에 대해 알아보세요.

포함된 C 언어의 공용체라고 하는 데이터 개체에 대해 알아보세요.

임베디드 C에서 구조체와 공용체의 차이점

이 시리즈의 이전 기사에서 임베디드 C의 구조를 사용하면 다양한 데이터 유형의 변수를 그룹화하고 단일 데이터 개체로 처리할 수 있다고 설명했습니다.

구조 외에도 C 언어는 다른 데이터 유형을 단일 데이터 개체로 그룹화할 수 있는 공용체라고 하는 또 다른 데이터 구조를 지원합니다. 이 기사는 노동 조합에 대한 몇 가지 기본 정보를 제공합니다. 먼저 공용체 선언의 소개 예제를 살펴본 다음 이 데이터 개체의 중요한 응용 프로그램을 살펴보겠습니다.

소개 예

공용체를 선언하는 것은 구조체를 선언하는 것과 비슷합니다. "struct" 키워드를 "union"으로 바꾸기만 하면 됩니다. 다음 예제 코드를 고려하십시오.

유니온 테스트 { uint8_t c; uint32_t 나는;}; 

이것은 1바이트를 차지하는 "c"와 4바이트를 차지하는 "i"라는 두 개의 멤버가 있는 템플릿을 지정합니다.

이제 이 통합 템플릿의 변수를 만들 수 있습니다.

유니온 테스트 u1; 

멤버 연산자(.)를 사용하여 "u1" 공용체의 멤버에 액세스할 수 있습니다. 예를 들어 다음 코드는 위 공용체의 두 번째 멤버에 10을 할당하고 "c" 값을 "m" 변수(uint8_t 유형이어야 함)에 복사합니다.

u1.i=10;m=u1.c; 

"u1" 변수를 저장하기 위해 얼마나 많은 메모리 공간이 할당됩니까? 구조체의 크기는 최소한 해당 멤버 크기의 합만큼 크지만 공용체의 크기는 가장 큰 변수의 크기와 같습니다. 공용체에 할당된 메모리 공간은 모든 공용체 구성원이 공유합니다. 위의 예에서 "u1"의 크기는 uint32_t의 크기, 즉 4바이트와 같습니다. 이 메모리 공간은 "i"와 "c" 간에 공유됩니다. 따라서 이 두 구성원 중 하나에 값을 할당하면 다른 구성원의 값이 변경됩니다.

"동일한 메모리 공간을 사용하여 여러 변수를 저장하는 것이 무슨 의미가 있습니까? 이 기능에 대한 응용 프로그램이 있습니까?" 이 문제는 다음 섹션에서 살펴보겠습니다.

공유 메모리 공간이 필요합니까?

공용체가 유용한 데이터 개체가 될 수 있는 예를 살펴보겠습니다. 아래 그림 1과 같이 시스템에 서로 통신해야 하는 두 개의 장치가 있다고 가정합니다.

그림 1

"장치 A"는 상태, 속도 및 위치 정보를 "장치 B"로 보내야 합니다. 상태 정보는 배터리 충전량, 작동 모드 및 주변 온도를 나타내는 세 가지 변수로 구성됩니다. 위치는 x축 및 y축 위치를 표시하는 두 개의 변수로 표시됩니다. 마지막으로 속도는 단일 변수로 표시됩니다. 이러한 변수의 크기는 다음 표와 같다고 가정합니다.

변수 이름 크기(바이트) 설명
파워 1 배터리 충전
op_mode 1 작동 모드
임시 1 온도
x_pos 2 X 위치
y_pos 2 Y 위치
2 속도

"장치 B"가 이 정보의 모든 조각을 지속적으로 필요로 하는 경우 이러한 모든 변수를 구조에 저장하고 구조를 "장치 B"로 보낼 수 있습니다. 구조 크기는 최소한 이러한 변수 크기의 합, 즉 9바이트만큼 커야 합니다.

따라서 "장치 A"가 "장치 B"와 통신할 때마다 두 장치 간의 통신 링크를 통해 9바이트 데이터 프레임을 전송해야 합니다. 그림 2는 “Device A”가 통신 링크를 거쳐야 하는 변수와 데이터 프레임을 저장하기 위해 사용하는 구조를 나타냅니다.

그림 2

그러나 가끔씩만 상태 정보를 보내야 하는 다른 시나리오를 고려해 보겠습니다. 또한 주어진 시간에 위치와 속도 정보를 모두 가질 필요는 없다고 가정합니다. 다시 말해 위치만 보낼 때도 있고 속도만 보낼 때도 있고 상태 정보만 보낼 때도 있습니다. 이런 상황에서 정보를 9바이트 구조로 저장하고 통신 링크를 통해 전달하는 것은 좋은 생각이 아닌 것 같습니다.

상태 정보는 3바이트로만 나타낼 수 있습니다. 위치와 속도의 경우 각각 4바이트와 2바이트만 필요합니다. 따라서 "장치 A"가 한 번의 전송으로 보내야 하는 최대 바이트 수는 4이고 결과적으로 이 정보를 저장하는 데 4바이트의 메모리만 필요합니다. 이 4바이트 메모리 공간은 세 가지 메시지 유형에서 공유됩니다(그림 3 참조).

또한 통신 링크를 통해 전달되는 데이터 프레임의 길이가 9바이트에서 4바이트로 줄어듭니다.

그림 3

요약하면, 우리 프로그램에 상호 배타적인 변수가 있는 경우 귀중한 메모리 공간을 보존하기 위해 메모리의 공유 영역에 변수를 저장할 수 있습니다. 이것은 특히 메모리가 제한된 임베디드 시스템의 맥락에서 중요할 수 있습니다. 이러한 경우, 우리는 공용체를 사용하여 필요한 공유 메모리 공간을 생성할 수 있습니다.

위의 예는 공용체를 사용하여 상호 배타적인 변수를 처리하는 것도 통신 대역폭을 절약하는 데 도움이 될 수 있음을 보여줍니다. 통신 대역폭을 절약하는 것이 때때로 메모리를 절약하는 것보다 훨씬 더 중요합니다.

메시지 패킷에 Union 사용

위 예제의 변수를 저장하기 위해 공용체를 사용하는 방법을 살펴보겠습니다. 상태, 위치 및 속도의 세 가지 메시지 유형이 있습니다. 상태 및 위치 메시지의 변수에 대한 구조를 만들 수 있습니다(이 메시지의 변수가 단일 데이터 개체로 그룹화되고 조작되도록).

다음 구조가 이러한 목적을 달성합니다.

struct { uint8_t 전력; unit8_t op_mode; uint8_t 임시;} 상태;구조체 { uint16_t x_pos; unit16_t y_pos;} 위치; 

이제 다음 구조를 "vel" 변수와 함께 유니온에 넣을 수 있습니다.

union {struct { uint8_t power; unit8_t op_mode; uint8_t 임시;} 상태;구조체 { uint16_t x_pos; unit16_t y_pos;} 위치; uint16_t vel;} msg_union; 

위의 코드는 유니온 템플릿을 지정하고 이 템플릿의 변수(이름:"msg_union")를 생성합니다. 이 공용체 내부에는 두 개의 구조("status" 및 "position")와 2바이트 변수("vel")가 있습니다. 이 합집합의 크기는 가장 큰 멤버의 크기, 즉 4바이트의 메모리를 차지하는 "위치" 구조와 같습니다. 이 메모리 공간은 "status", "position" 및 "vel" 변수 간에 공유됩니다.

조합 활동 회원을 추적하는 방법

위의 공용체의 공유 메모리 공간을 사용하여 변수를 저장할 수 있습니다. 그러나 한 가지 질문이 남아 있습니다. 수신자는 어떤 유형의 메시지가 전송되었는지 어떻게 결정해야 합니까? 수신자는 수신된 정보를 성공적으로 해석할 수 있도록 메시지 유형을 인식해야 합니다. 예를 들어 "위치" 메시지를 보내면 수신된 데이터의 4바이트 모두가 중요하지만 "속도" 메시지의 경우 수신된 바이트 중 2바이트만 사용해야 합니다.

이 문제를 해결하려면 우리의 공용체를 메시지 유형(또는 마지막으로 작성된 공용체 구성원)을 나타내는 "msg_type"과 같은 다른 변수와 연결해야 합니다. Union의 활성 구성원을 나타내는 이산 값과 쌍을 이루는 Union을 "discriminated union" 또는 "tagged union"이라고 합니다.

"msg_type" 변수의 데이터 유형과 관련하여 C 언어의 열거 데이터 유형을 사용하여 기호 상수를 생성할 수 있습니다. 그러나 가능한 한 간단하게 유지하기 위해 문자를 사용하여 메시지 유형을 지정합니다.

struct { uint8_t msg_type;union {struct { uint8_t 전력; unit8_t op_mode; uint8_t 임시;} 상태;구조체 { uint16_t x_pos; unit16_t y_pos;} 위치; uint16_t vel;} msg_union;} 메시지; 

"msg_type" 변수에 대해 세 가지 가능한 값을 고려할 수 있습니다. 's'는 "상태" 메시지, 'p'는 "위치" 메시지, 'v'는 "속도" 메시지입니다. 이제 "message" 구조를 "Device B"로 보내고 "msg_type" 변수의 값을 메시지 유형의 표시기로 사용할 수 있습니다. 예를 들어, 수신된 "msg_type"의 값이 'p'인 경우 "장치 B"는 공유 메모리 공간에 2개의 2바이트 변수가 포함되어 있음을 알 수 있습니다.

"msg_type" 변수를 전송해야 하기 때문에 통신 링크를 통해 전송된 데이터 프레임에 다른 바이트를 추가해야 합니다. 또한 이 솔루션을 사용하면 수신자가 어떤 종류의 메시지가 수신되는지 미리 알 필요가 없습니다.

대체 솔루션:동적 메모리 할당

우리는 공용체를 통해 공유 메모리 영역을 선언하여 메모리 공간과 통신 대역폭을 모두 보존할 수 있음을 확인했습니다. 그러나 위의 예와 같이 상호 배타적인 변수를 저장하는 다른 방법이 있습니다. 이 두 번째 솔루션은 동적 메모리 할당을 사용하여 각 메시지 유형의 변수를 저장합니다.

다시 말하지만, 통신 링크의 송신기와 수신기 쪽 모두에서 메시지 유형을 지정하려면 "msg_type" 변수가 필요합니다. 예를 들어, "장치 A"가 위치 메시지를 보내야 하는 경우 "msg_type"을 'p'로 설정하고 "x_pos" 및 "y_pos" 변수를 저장하기 위해 4바이트의 메모리 공간을 할당합니다. 수신기는 "msg_type"의 값을 확인하고 그 값에 따라 들어오는 데이터 프레임을 저장하고 해석하기 위한 적절한 메모리 공간을 만듭니다.

동적 메모리를 사용하면 각 메시지 유형에 대해 충분한 공간만 할당하기 때문에 메모리 사용 측면에서 더 효율적일 수 있습니다. 노조 기반 솔루션의 경우는 그렇지 않았습니다. 거기에는 세 가지 메시지 유형을 모두 저장할 수 있는 4바이트의 공유 메모리가 있었지만 "상태" 및 "속도" 메시지에는 각각 3바이트와 2바이트만 필요했습니다. 그러나 동적 메모리 할당은 더 느릴 수 있으며 프로그래머는 할당된 메모리를 해제하는 코드를 포함해야 합니다. 이것이 프로그래머들이 일반적으로 Union 기반 솔루션을 선호하는 이유입니다.

다음 단계:조합의 적용

Union의 원래 목적은 상호 배타적인 변수에 대한 공유 메모리 영역을 만드는 것 같습니다. 그러나 공용체는 더 큰 데이터 개체에서 더 작은 데이터 부분을 추출하는 데에도 널리 사용되었습니다.

이 시리즈의 다음 기사에서는 임베디드 애플리케이션에서 특히 중요할 수 있는 공용체 적용에 초점을 맞출 것입니다.

내 기사의 전체 목록을 보려면 이 페이지를 방문하십시오.


임베디드

  1. 산업용 사물 인터넷 애플리케이션을 위한 최고의 프로그래밍 언어
  2. 마이크로프로세서 프로그래밍
  3. 데이터로 무엇을 해야 합니까?!
  4. 사물인터넷 민주화
  5. 2021년에 배워야 할 9가지 새로운 프로그래밍 언어
  6. C - 조합
  7. 데이터 센터의 미래
  8. IoT의 클라우드
  9. 논평:로봇 프로그래밍 방법 이해
  10. 동일한 산업 언어 말하기:압축기의 일반적인 측정 단위 이해