[Embedded] 프로토콜의 원리, 1-Wire 통신, 소스코드 분석

강지원·2025년 3월 21일

STM32 강의

목록 보기
31/33

1-Wire 통신

Dallas Semiconductor Corp. 에서 만든 통신 방식

장점 : 딱 2개의 선으로 전원 공급과, 양방향 통신 가능

  1. 장거리 힘들겠다(노이즈에 약함) ex)RS232
  2. 주소 체계 방식을 쓰겠군 ex)RS485
  3. 빠른 속도 불가능(클럭선 x -시간 Base)
  4. 간단해서 많이 사용?

프로토콜의 종류

  1. 물리적인 통신 방식만을 규정한 프로토콜(SPI)
  2. 물리적 + 소프트웨어적인 규칙까지 정한 프로토콜(1-Wire)
  3. 소프트웨어적인 규칙만 정의한 프로토콜(http, 모드버스, tcp)
  4. layer가 있는 프로토콜

1-Wire 통신 시작 방법

전압, 시간

전압 5V : 1, 낮은V : 0

  1. 데이터 HIGH 신호 기본
  2. MASTER RESET PULSE(데이터 LOW신호를 최소 480us 보내라)
  3. SLAVE Wait(최소 15~60us 기다려라)
  4. SLAVE presense pulse(데이터 LOW신호를 60 ~ 240us 보내라)
    슬래이브가 존재하고 있다는 신호를 주기 위함
  5. 통신 시작함

-> Reset Pulse

1-Wire 명령어 종류

마스터가 통신시작을 알리고, presence pulse를 수신한 후에 아래와 같은 명령어들을 보낼 수 있음

슬레이브는 ROM code(주소)를 갖는다

ROM 명령어 종류

  • ROM command : 장치를 선택하기 위한 명령어

  • Function command : 장치에게 특정 동작을 수행하기 위한 명령어

  • Search ROM : 0xF0
    1-Wire bus에 연결된 모든 slave 장치들의 ROM code를 읽는다.

  • Match ROM: 0x55
    Match ROM command 를 보낸 뒤 64비트의 ROM code를 보낸다. 이 ROM code에 맞는 slave 장치에 접근하기 위해 이 command를 사용 나머지 slave장치들은 reset pulse를 기다림

  • Skip ROM : 0xCC
    모든 슬레이브 장치에게 동시에 command를 보낼 때 사용

  • Alarm search : 0xEC
    슬레이브 장치의 Alarm flag가 set 상태인지 확인할 때 사용

Function 명령어

제조사마다 다르다.. 사용하려는 센서마다 다름

scratchpad : DS18B20의 메모리
메모리는 우리가 생각하는 물리적인 메모리가 아닌 경우가 많다

  • Convert T: 0x44
    온도의 변환 시작. 신호선으로 전원을 공급받는 경우 이 command를 보낸뒤 신호선을 high상태로 올려서 온도를 변환하는 동안 전원을 공급해야 함
    온도의 변환시간 : 93.75ms(9비트) ~ 750ms(12비트)

  • Write scratchpad : 0x4E
    3바이트의 데이터를 장치의 scratchpad에 쓴다

  • Read scratchpad : 0xBE
    scratchpad의 값을 읽어온다

  • copy scratchpad: 0x48
    scratchpad의 값을 EEPROM으로 저장한다.
    신호선으로 전원을 공급하는 경우, command를 보낸뒤 신호선을 10us동안 HIGH 상태 유지

  • Recall E^2: 0xb8
    현재 Alarm 쓰레스 홀드 값(TH, TL)
    configuration data를 EEPROM에서 불러와서 scratchpad 2,3,4바이트에 기록
    *쓰레스 홀드 값: 기준값
    기준값을 넘으면 alar이 울ㄹ림

  • Read power supply: 0xB4
    전원공급 출처 확인
    VDD핀 or 신호선

  • 등등 더 많은 명령어..

데이터를 주고 받는 방법

.. 소스코드를 확인

한 slot에 한 비트를 보냄
slot의 시간 간격은 1us이상

마스터:
0을 전송할 때는 60~120us low
1을 전송할 때는 1us low
시간에 따라서 0,1을 구분한다는 의미

slave는 15~60us 사이에 샘플링 후 값 읽기

slave는 마스터가 1us이상 신호선을 low로 내려야 전송가능

slave가 0을 표현할 때 15us 동안만 low로 내릴 수 있음
때문에 마스터는 15us 안으로 값을 읽어야함

1-Wire 소스분석

ROM Search(통신하는 원리)

  • Search ROM : 0xF0
    1-Wire bus에 연결된 모든 slave 장치들의 ROM code를 읽는다.

어떻게 장치들을 찾아내지?

  1. 마스터가 0xF0를 보냄

아래 3가지 단계를 반복한다

  1. 한 Bit를 읽는다
  2. 비트의 보수를 읽는다
  3. (경우의 수에 의한) 0 또는 1을 write한다

통신원리 설명

시작

  1. 리셋 펄스를 보냄(master - 480us low)
  2. slave 디바이스 응답 (slave 15~60us wait, slave presence pulse - 60~240us low)
  3. 써치 커맨드 보냄 0xF0
  4. 비트를 읽음

써치 커맨드 원리

예시)
ROM1 00110101... (64비트)
ROM2 10101010...
ROM3 11110101...
ROM4 00010001...
  1. 0xF0 : 써치 커맨드 보냄

  2. 마스터 read - 1Bit씩 읽음

  3. ROM1,2,3,4 가 각각 자신의 주소의 첫번째 비트를 보냄(0,1,1,0)

  4. 마스터 입장에서는 0으로 읽힘
    왜 ? 한 Slot에 한 비트를 보낼 때 슬롯의 시간 간격은 1us 이상
    0으로 전송할 때는 60~120us low, 1을 전송할 때는 1us low
    시간에 따라서 0,1을 구분함
    따라서 0,1,1,0 신호가 한번에 겹쳐서 오기 때문에 60us~120us인 0으로만 인식함

  5. 각 비트를 다시 보수를 취해서 1번 더 보냄(1,0,0,1)

  6. 마스터 입장에서는 0으로 읽힘

  7. 이제 경우의 수를 분석
    00 연결된 장치들의 비트가 1,0 섞여있음
    01 연결된 장치들의 비트가 모두 0임
    10 연결된 장치들의 비트가 모두 1임
    11 연결된 장치가 없음

  8. 경우의 수를 따지면서 한비트씩 다 분석해서 주소를 찾아냄
    00 일땐 체크해서 0을 보냄 -> 그럼 rom2,3의 첫번째비트는 1이기 때문에 둘은 빠짐 -> rom1,4만 남음 -> 또 다음 비트 읽음 -> 01 일땐 두 장치 전부 0 -> 다음 비트 읽음 00이 옴 -> 체크를 해서 0을 보내면 rom1이 탈락되고 rom4만 남음 -> 그대로 읽으면 rom4의 주소를 읽게 됨(64비트) 이 주소를 저장해 놓음 그 후부터는 그 주소를 부르면 rom4가 호출
    다음엔 마지막 체크해 놓은 00에서 1을 보내봄 -> 따라서 rom1만 남으면서 rom1의 주소 확인 반복..

소스코드 분석

  1. 칩 자체의 클래스(Ds18b20)
  2. 통신 방식의 클래스(one-wire)
typedef struct {
	GPIO_TypeDef* GPIOx;           /*!< GPIOx port to be used for I/O functions */
	uint16_t GPIO_Pin;             /*!< GPIO Pin to be used for I/O functions */
	uint8_t LastDiscrepancy;       /*!< 마지막 불일치*/
	uint8_t LastFamilyDiscrepancy; /*!<  */
	uint8_t LastDeviceFlag;        /*!< 위에서 찾아낸 논리에서의 체크 플래그 */
	uint8_t ROM_NO[8];             /*!< 찾아낸 8바이트의 rom의 주소 */
} OneWire_t;

각각의 init 부터 시작해서 search rom 함수 까지 읽으면서 분석해보면
마스터가 보내기 전에 몇초 low신호 보내기,
슬레이브가 보내기 전에 몇초 low신호 보내기
이런 규칙을 지키면서 진행하고 있다

bool Ds18b20_Init(void) : 온도센서 초기화

  1. 타이머 시작,gpio 세팅
  2. 0xf0명령어를 통해 장치 하나를 찾음
  3. 찾은 장치의 주소를 저장
  4. 다음 장치를 찾음
  5. 온도센서의 resolution(해상도) 설정
  6. 온도센서의 알람을 해지함

onewire 함수의 구조

  1. reset
  2. rom(주소) 설정
  3. 명령어 보내기 (1 byte 송신)
  4. 1 byte 수신

Ds18b20_ManualConvert(); 온도를 계속 읽어옴

void DS18B20_StartAll(OneWire_t* OneWire) /*온도 변환 시작*/
{
	/* Reset pulse */
	OneWire_Reset(OneWire);
	/* Skip rom  모든 슬레이브 장치를 부름 */
	OneWire_WriteByte(OneWire, ONEWIRE_CMD_SKIPROM);
	/* Start conversion on all connected devices  function command 온도변환 시작*/
	OneWire_WriteByte(OneWire, DS18B20_CMD_CONVERTTEMP);
}

convert T : 0x44
온도의 변환 시작

  • 신호선으로 전원을 공급받는 경우 : 이 command를 보낸 뒤 신호선을 high 상태로 올려서 온도를 변환하는 동안 전원을 공급해야함.
  • 외부전원일 경우 : 진행(0) 완료(1)응답이 옴

[온도의변환시간]
93.75ms(9비트) ~ 750ms(12비트)

온도센서 검증방법

온도계 사서 비교,...

상용화를 위해서는 검증기관에 가서 검증받아야 함

0개의 댓글