AD7280A는 모든 프레임에 CRC가 들어간다. CRC가 틀리면 명령을 무시한다.
여기서 3일 날렸다.
AD7280A CRC 스펙
- CRC-8
- 다항식: 0x2F (x^8 + x^5 + x^3 + x^2 + x + 1)
- 초기값: 0x00
- 입력 데이터: 프레임의 bit 31~11 (21비트)
데이터시트에 이렇게 써있다. 간단해 보였다.
첫 번째 시도
uint8_t AD7280A_CalcCRC(uint32_t data) {
uint8_t crc = 0;
for (int i = 20; i >= 0; i--) {
uint8_t bit = (data >> i) & 0x01;
if ((crc ^ bit) & 0x01) {
crc = (crc >> 1) ^ 0x2F;
} else {
crc >>= 1;
}
}
return crc;
}
결과: AD7280A가 응답 안 함.
두 번째 시도
CRC 방향이 잘못됐나? MSB first로 바꿔봤다.
uint8_t AD7280A_CalcCRC(uint32_t data) {
uint8_t crc = 0;
for (int i = 20; i >= 0; i--) {
uint8_t bit = (data >> i) & 0x01;
if ((crc ^ (bit << 7)) & 0x80) {
crc = (crc << 1) ^ 0x2F;
} else {
crc <<= 1;
}
}
return crc;
}
결과: 여전히 응답 없음.
데이터시트 예제 확인
데이터시트에 예제가 있었다.
Input: 0x1C0E10 (21bit)
Expected CRC: 0xA7
내 함수로 계산하면 0x5E가 나온다. 완전히 다르다.
결국 찾은 문제
하루 종일 삽질하다가 EngineerZone에서 힌트를 찾았다.
“The CRC polynomial should be bit-reversed: 0xF4 instead of 0x2F”
다항식을 비트 반전해야 한다고? 0x2F를 뒤집으면 0xF4.
// 0x2F = 0b00101111
// 뒤집으면 0b11110100 = 0xF4
그리고 입력 데이터도 비트 순서가 다르다.
최종 코드
static uint8_t crc_table[256];
void AD7280A_BuildCRCTable(void) {
for (int i = 0; i < 256; i++) {
uint8_t crc = i;
for (int j = 0; j < 8; j++) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x2F;
} else {
crc <<= 1;
}
}
crc_table[i] = crc;
}
}
uint8_t AD7280A_CalcCRC(uint32_t val) {
// 21비트 데이터를 3바이트로 처리
uint8_t crc;
crc = crc_table[(val >> 16) & 0xFF];
crc = crc_table[crc ^ ((val >> 8) & 0xFF)];
crc = crc_table[crc ^ (val & 0xFF)];
return crc;
}
룩업 테이블 방식으로 바꿨다. 초기화할 때 테이블 만들어놓고 참조만 하면 된다.
결과: 드디어 응답이 온다!
검증
데이터시트 예제로 검증:
AD7280A_BuildCRCTable();
uint8_t crc = AD7280A_CalcCRC(0x1C0E10);
printf("CRC: 0x%02X\n", crc); // 출력: 0xA7
맞다!
왜 이렇게 헷갈리게 해놨을까
솔직히 데이터시트 설명이 불친절하다.
“Polynomial: 0x2F"라고만 써있고, 구현 방식(반영 여부, 비트 순서)은 안 써있다.
결국 예제 하나 맞춰보는 게 제일 확실하다.
CRC 검증 함수
수신 프레임의 CRC 검증:
bool AD7280A_CheckCRC(uint32_t frame) {
uint32_t data = frame >> 11; // bit 31~11 추출
uint8_t received_crc = (frame >> 3) & 0xFF;
uint8_t calculated_crc = AD7280A_CalcCRC(data);
return (received_crc == calculated_crc);
}
수신할 때마다 CRC 체크해서 통신 오류 검출.
정리
- 다항식: 0x2F
- 21비트 입력 (bit 31~11)
- 룩업 테이블 방식이 빠르고 편함
- 데이터시트 예제로 꼭 검증
3일 걸렸지만 한번 되고 나니까 그 뒤론 문제없었다.
Part 2 드라이버편 끝.
다음은 셀 전압 읽기. 드디어 뭔가 측정한다.