冰箱坚称自己有255°C
한국어 원문으로 표시합니다.
한 줄 요약
센서가 보낸 두 바이트는 아직 온도가 아닙니다. 순서·부호·단위를 설명할 수 있어야 숫자를 믿을 수 있습니다.
왜 이게 필요했나
냉장고가 255°C라고 우깁니다. 실제 과열이라고 바로 단정할 수도, 표시 버그라며 무시할 수도 없습니다. 이번 이야기는 합성 고장 상황입니다. 먼저 원시 바이트, 변환 규약, 출력 단위를 분리해서 재현합니다. 잘못된 값이 어느 경계에서 생겼는지 찾는 연습이며 실제 냉장고 제어·안전 장치를 설계하는 과정은 아닙니다.
C 함수·포인터·구조체의 기초를 알고 시작하세요. 함수는 결과를 반환값 하나에 다 넣지 않습니다. 반환값은 성공 여부이고 온도는 출력 포인터에 씁니다. 실패 때 이전 값이 남아 있어도 이번 호출이 성공한 것은 아닙니다. 호출자는 상태 코드와 값을 함께 취급해야 합니다.
어떻게 동작하나
이번 TMP102 온도 레지스터 변환은 상위 바이트를 먼저 받습니다. 정상 모드는 12비트, 확장 모드는 13비트 2의 보수이며 한 카운트는 0.0625°C입니다. 두 번째 바이트의 bit 0으로 모드를 구별합니다. 상세 배치는 공식 데이터시트 표 6-8·6-9를 확인하세요.
실습에서는 부동소수점 대신 마이크로 섭씨 정수를 사용합니다. 1°C는 1,000,000, 한 카운트는 62,500입니다. 소수점을 버린 다음 단위를 바꾸면 작은 음수와 분수 값이 사라집니다. 먼저 카운트를 정확히 구하고 마지막에 단위를 바꿉니다.
정상 모드의 0x19 0x00은 25°C, 0xff 0xf0은 -0.0625°C입니다. 0xff를 부호 없는 온도 255로 바로 표시하는 것은 바이트와 물리량을 혼동한 예입니다. 12비트 숫자에서 부호 비트가 켜졌다면 양의 정수로 읽은 카운트에서 4096을 빼면 됩니다. 확장 모드는 이 폭이 달라집니다. 음수의 오른쪽 시프트에 기대지 않고 명시적으로 복원하는 이유는 C 구현 차이를 줄이기 위해서입니다.
예약 비트가 켜진 입력은 이 과제에서 SENSOR_FORMAT으로 거부하며 출력은 그대로 둡니다. 이는 과제의 유효 입력 정책이지 모든 센서의 일반 규칙이 아닙니다. 헤더 sensor.h의 함수 선언과 상태 열거형을 먼저 읽으세요. main 함수는 검사기가 제공하므로 제출 파일에는 두 함수만 구현합니다.
손으로 변환해 보고 코드의 가설을 세운다
다음 표는 계측값이 아니라 변환 규약으로 만든 계산 예제입니다. 먼저 종이에 카운트를 구한 뒤 마지막 열과 비교하세요. 마이크로 섭씨 열은 단위가 붙은 정수이며 천 단위 쉼표를 생략했습니다.
| 두 바이트 | 모드 | 부호 복원한 카운트 | 마이크로 섭씨 |
|---|---|---|---|
| 0x19 0x00 | 정상 | 400 | 25000000 |
| 0x0a 0x10 | 정상 | 161 | 10062500 |
| 0xff 0x50 | 정상 | -11 | -687500 |
| 0xff 0xf0 | 정상 | -1 | -62500 |
| 0x4b 0x01 | 확장 | 2400 | 150000000 |
세 번째 행을 풀어 봅시다. 바이트를 결합한 0xff50에서 하위 네 비트를 제외하면 0xff5, 즉 4085입니다. 이 값은 12비트 부호 경계 2048 이상이므로 4085−4096=−11입니다. 여기에 62,500을 곱하면 −687,500, 섭씨로는 −0.6875°C가 됩니다. 앞 바이트만 읽거나 섭씨 정수로 먼저 나누면 이 작은 음수가 사라집니다. 다섯 번째 행은 하위 bit 0이 1이므로 세 비트를 제외해야 합니다. 모드 비트만 확인하고 시프트 폭을 그대로 두면 같은 바이트를 다른 온도로 해석합니다.
C에서 부호 복원은 연산하는 자료형까지 포함한 약속입니다. 시프트한 비음수 카운트는 최대 8191이라 int32_t에 들어갑니다. 이 범위에서 먼저 부호 있는 변수로 옮긴 다음 4096 또는 8192를 빼면 음수를 명시적으로 만들 수 있습니다. 반대로 unsigned 상태에서 먼저 빼면 큰 양수로 돌아갑니다. 그 결과를 나중에 signed로 바꾸는 방법에 기대지 마세요. 완성된 카운트의 절댓값은 최대 4096이므로 62,500을 곱한 결과도 int32_t 범위 안입니다. 중간 계산과 최종 저장 둘 다 범위를 확인하는 습관이 중요합니다.
이제 반례를 만듭니다. 표의 0x0a 0x10을 뒤집어 읽으면 0x100a가 되어 이번 정상 모드의 예약 비트 정책에도 어긋납니다. 반면 0x00 0x00은 순서를 뒤집어도 변하지 않습니다. 따라서 ‘0이 나왔다’는 테스트와 ‘순서가 맞다’는 테스트는 같지 않습니다. 정상 입력을 고른 이유와 그 입력이 구별하지 못하는 결함을 함께 적으세요.
현장에서 만나는 모습
재현 보고서에는 화면의 숫자뿐 아니라 원시 바이트·모드·출력 단위를 남깁니다. 바이트 순서가 잘못된 코드도 일부 값에서는 우연히 맞습니다. 0만 시험하면 순서를 바꾼 코드와 올바른 코드가 구별되지 않습니다. 그래서 양수·0·작은 음수·경계·예약 비트까지 나눠 봅니다.
표현 가능한 수와 물리적 동작 범위도 다릅니다. 확장 인코딩의 150°C 계산이 맞아도 실물 TMP102의 그 온도 동작을 보증하지 않습니다. 분해능이 세밀하다는 것 또한 측정 정확도가 그만큼 좋다는 뜻은 아닙니다.
이어서 확인할 것
바로 이어지는 퀴즈에서는 계산 순서와 반례를 확인합니다. 이후 실패·시간 계약을 읽고 마지막 모듈의 누적 C 실습으로 넘어갑니다. 실습의 1~3단계에서 sensor_decode를 구현하며 양수 전체 범위, 음수 전체 범위, 두 모드와 오류 입력을 차례로 검사합니다. 컴파일러 경고도 먼저 해결하고, 표의 몇 개 값만 하드코딩하지 마세요.