1. 1-Wire 통신에서 장치 찾는방법
- 마스터가 특정 장치의 주소를 찾을 때, 그 장치가 마스터에게 어떻게 하나의 선으로 물려있는데 자신의 주소를 보낼까?
1-1. 크게 4 STEP
- Rom Search 0xF0를 통해 Master가 Slave들에게 전송
- 한 bit를 읽는다
- 비트의 보수를 읽는다
- (경우의 수에 의한) 0 또는 1을 Write 한다
1-2. 쉽게 더 풀어 설명하자면,
- Master에서 480μs 이상을 Low로 떨어트리면(Reset 신호) 통신 시작을 의미한다는 의미로, Slave들은 들을 준비
- Slave에서 60~240μs를 Low로 떨어트려서 신호 전송(presence 펄스)
- Master는 그걸 읽고 장치가 존재하고 장치들이 들을 준비가 되었다는 것을 확인
- Master는 Search command인 'Rom Search 0xF0' 전송
- 비트 read
EX) 장치 찾아내기 (1 Wire에서는 주소 체계가 64bit이므로 ...로 생략)
ROM1 00110101...
ROM2 10101010...
ROM3 11110101...
ROM4 00010001...
- Master와 Slave의 통신 시작함을 주고받고 Master가 1bit를 읽는다 (1번째 bit)
- ROM1~4는 Master에게 각각 자기 주소의 첫 번째 bit를 보냄
=> ROM1 : 0/ ROM2: 1/ ROM3: 1/ ROM4: 0 - Master는 0110을 동시에 받으면 0으로 read
cf. 0 전송 : 60~120μs동안 low로/ 1 전송 : 1 μs동안 low로 떨어트리기에 0110을 보내면 1이 0에 덮여짐 - ROM1~4는 다시 보수를 취해서 1001을 Master에게 또 전송
- Master는 이번에도 0으로 read
- Master는 00으로 경우의수를 따짐
=> 00 : 연결된 장치들의 비트가 1,0이 섞여있음
=> 01 : 연결된 장치들의 비트가 모두 0임
=> 10 : 연결된 장치들의 비트가 모두 1임
=> 11 : 연결된 장치가 없음 - 00이므로 (0,0)을 chk하고 Master는 0을 보내는 순간 ROM2,3는 자신의 주소 첫번째 bit가 1이므로 '나는 아니구나'라고 생각하고 탈락되고, ROM1,4만 응답
- Master는 그 다음 bit를 읽음 (2번째 bit)
- ROM1,4는 두번째 bit가 0,0이므로 0 보내고 보수 취했을 때는 1,1이므로 1을 보내기에 Master에게 01이 전송됨
- Master는 01을 받았으므로 두 장치가 모두 0임을 알아냄
- Master는 그 다음 bit를 읽음 (3번째 bit)
- Master는 (0,1)을 고려하고 Master는 0을 보내는 순간 ROM1,4는 두 번째 bit가 0이었기에 둘 다 살아남고, 자신의 주소 세번째 bit가 1,0이므로 0보내고 보수 취했을 때는 0,1이므로 0을 보내기에 Master에게 00이 전송됨
- Master는 장치가 두 개이상 있음을 확인하고 (0,0)을 chk하고 Master는 0을 보내는 순간 ROM1이 탈락되어 ROM4만 남게되고 계속 64bit를 읽어서 찾아냄
- chk한 분기점을 오른쪽에서 왼쪽 순서대로 Master가 0을 보냈었다면 이번엔 1로, 1을 보냈었다면 이번엔 0을 보내서 다른 ROM의 주소들을 찾아냄
=> Master는 4가지 경우의 수를 이용해서 ROM들의 주소를 찾아낸다
2. 본격적인 소스 코드 해석
2-1. Ds18b20_Init();
: 대부분 Init 함수부터 모든 동작이 시작됨
- 칩 자체에 대한 소스가 모여 있는 클래스 + 1-Wire 통신 방식에 대한 소스가 모여 있는 클래스
=> ds18b20.c : 칩 자체 / ds18b20.c 내 Ds18b20_Init()함수의 OneWire_Init() 함수 : 1-Wire 통신 방식
=> 이때, OneWire_Init() 인자로 주는 &OneWire는 OneWire_t로 정의된 타입(사용자 정의 구조체)
=> ROM_NO[8]은 ROM들의 주소(64bit)가 저장 (* unsigned char: uint8_t 이므로 1byte)
+ LastDiscrepancy : 장치 주소 찾기 위해 설정한 분기점들
- OneWire_Init 함수 통해서 우리가 define 해놓은 GPIO PA3 핀을 초기화 설정
- HAL_GetTick()이 3초(3000) 미만이면 Ds18b20Delay(100); 수행
* 이때 Ds18b20Delay(100);는 HAL_Delay 함수 - 수행하고 OneWire_First 함수를 통해 OneWire에 대해 분기점 설정해놓았던 플래그 bit들 0으로 초기화
- 이 함수는 ROM들이 자신의 주소의 1bit를 보내는 동작들이 모두 포함되어있음
* ONEWIRE_CMD_SEARCHROM 은 0xF0으로 정의되어있음 (Master의 Search 명령어)
- OneWireStruct->LastDeviceFlag : 모든 장치들의 주소들을 찾았는지 확인하는 flag
- 만약 다 찾지 못했다면 OneWire_Reset 함수 수행
- 1이라면 장치가 없는 것이므로 0으로 초기화하고 0을 반환 / 0이라면 OneWire_WrieByte 수행
=> 이때 0이면 보내는 시간이 길고 1이면 짧음 - 결론적으로, Master는 0xF0을 보냄
- 0은 길게, 1은 짧게되어 Master는 Slave들의 bit를 0 또는 1을 read하여 id_bit에 저장
- 그 bit들을 보수취하여 다시 Master에게 전송이 되고 그 bit들을 0또는 1로 read하여 cmp_id_bit에 저장
- 그 다음 왼쪽 사진의 if문을 통해 두 bit 모두 1이면 장치가 없는 것이므로 break/ 아니라면 else문 수행
- 00/01/10인 경우 수행할 함수들 쫙 나열되어있음
2-2. 총정리
- main.c 내의 Ds18b20_Init(void); 수행
- Ds18b20_Init(void) 내 OneWire_Init(&OneWire,_DS18B20_GPIO ,_DS18B20_PIN); 수행하여 Pin과 GPIO 통해 OneWire 구조체 대략적으로 설정 후 GPIO신호를 H-L-H-L 한 번 보내줌
- Ds18b20_Init(void) 내에서 HAL_GetTick()을 통해 3초 미만이라면 Ds18b20Delay(100); 통해 일정 시간 wait
- Ds18b20_Init(void) 내 OneWireDevices = OneWire_First(&OneWire);을 통해 OneWire_ResetSearch(OneWireStruct); 수행 후 return OneWire_Search(OneWireStruct, ONEWIRE_CMD_SEARCHROM);문을 통해 장치 하나를 찾아냄 (찾으면 1, 못찾으면 0)
=> 이때 그 장치의 주소는 OneWire_t의 ROM_NO[8]에 저장 - OneWireDevices에 1이 반환되면 Ds18b20_Init(void) 내 while문을 통해 TempSensorCount 1 증가시키고 OneWire_GetFullROM(&OneWire, ds18b20[TempSensorCount-1].Address);을 통해 여러 장치의 주소를 저장할 수 있게함
- OneWireDevices = OneWire_Next(&OneWire); 통해 다음 장치를 계속해서 찾아냄
- 장치를 하나라도 찾으면 while문을 빠져나오고 하나도 못찾으면 초기에 설정해놓은 Ds18b20TryToFind = 5;을 통해 5번 더 장치 찾기 시도
=> 5번 모두 못찾으면 false 반환 - 찾았다면, DS18B20_SetResolution(&OneWire, ds18b20[i].Address, DS18B20_Resolution_12bits); 과 DS18B20_DisableAlarmTemperature(&OneWire, ds18b20[i].Address);을 통해 온도의 정밀도 세팅 후 쓰레스홀드 설정 (일정 이상 온도가 되면 알람 울리는 걸 disable 하는 동작)
'임베디드' 카테고리의 다른 글
[오제이 튜브의 임베디드 강의] 28강. 드라이기를 내 마음대로 껐다, 켰다 해보자 (0) | 2025.02.05 |
---|---|
[오제이 튜브의 임베디드 강의] 27강. 온도센서 검증하기! (0) | 2025.02.05 |
[오제이 튜브의 임베디드 강의] 25강. 어디서도 안 알려주는 프로토콜의 원리! (2) | 2025.01.28 |
[오제이 튜브의 임베디드 강의] 24강. 1-Wire통신! 나름 유명했다. (온도센서) (0) | 2025.01.28 |
[오제이 튜브의 임베디드 강의] 23강. 온도센서를 붙여보자! (0) | 2025.01.26 |