본문 바로가기
임베디드

[오제이 튜브의 임베디드 강의] 24강. 1-Wire통신! 나름 유명했다. (온도센서)

by 덤더리덤떰 2025. 1. 28.

1. 1-Wire 통신의 개요 

  • 1-Wire 라이브러리 존재 (<=> 유명하다)
  • STM32에서 HAL 라이브러리에 존재
    cf. HAL(Hardware Abstraction Layer) : STMicroelectronics에서 제공하는 하드웨어 추상화 계층 라이브러리로, STM32 마이크로컨트롤러에서 하드웨어를 보다 쉽게 제어할 수 있도록 도와주는 소프트웨어 계층

1-1. 1-Wire 통신이란?

 

  • Dallas Semiconductor Corp에서 만든 통신 방식
  • 1-wire 버스를 사용하면 핀 하나만으로 통신 할 수 있고, 이 신호선으로 전원까지 공급 가능
  • 1-wire bus는 선 한개로 데이터 송/수신을 하기에 1-wire bus 방식의 IC와 연결하는 MCU는 GPIO핀의 입/출력 모드 번갈아 사용 
    => 1-wire에서 read_bit 함수는 1-Wire 프로토콜의 특성 때문에, 데이터 읽기 전 반드시 OUTPUT → LOW → 쉬기 → INPUT → 데이터 읽기 과정을 거쳤었음


1-2. 라이브러리 포팅하기

  • 이전 시간에 생성했던 second 폴더는 FND를 STM32에서 제공하는 방식으로 제어 / first 폴더는 GPIO 통해 FND 제어 
    => second 폴더로 포팅하기 
  • 아래 사진과 같이 Core 내에 Lib 폴더 생성 후 Inc/Src 폴더 생성 

  • 주변 장치 자료\온도센서\ds18b20-master의 ds18b20.c와 onewire.c는 Src 폴더에 
  • 주변 장치 자료\온도센서\ds18b20-master의 ds18b20.h와 ds18b20Config.h와 onewire.h는 Inc 폴더에 
  • 컴파일하면 에러가 뜨는데 이 에러들을 수정하는 게 오늘의 목표 

1-3. 에러 수정

 


(1) onewire.h와 ds18b20.h의 fatal error

  • Core - Properties에 들어가서 직접 include 해주기

 


(2) 또다른 에러 gpio.h의 fatal error 발생

  • gpio.h 주석 처리하고 다시 컴파일 하면 unknown type name 'GPIO_TypeDef' 오류 발생 

(왼) gpio.h의 fatal error 발생 (오) gpio.h 주석 처리 후 에러

 

=> GPIO_TypeDef의 정의는 stm32f103xb.h에 정의 

=> 이때 main.c에서 main.h를 include 하는데 main.h에서 stm32f103xb.h를 include 하고 있음 

=> onewire.h에서 오류났으므로 여기서 main.h를 include 하자 


(3) 새로운 에러 cmsis_os.h의 fatal error 발생

  • 이때 cmsis_os.h를 include하는 조건은 _DS18B20_USE_FREERTOS == 1 인 경우이다
  • 따라서 이 값을 0으로 설정하여 cmsis_os.h를 include하지 않도록함
  • 최종적으로 else문이 수행되어 HAL_Delay(x) 의 define문이 수행

(4) 새로운 에러 tim.h의 fatal error 발생하여 주석 처리 후 다시 컴파일

=> GPIO,PIN,TIMER 설정하지 않아 생기는 오류 발생

 

1) GPIO, PIN 세팅하기 위해 second.ioc 설정

  • 데이터시트를 보면 온도 관련 핀이 PA3_TEMP-DATA이므로 PA3 제어 

  • 이때 핀들에 대한 정의는 main.h에 있으므로 현재 우리가 GPIO, PIN 세팅해야 하는 ds18b20Config.h에 main.h를 include
  • main.h에 정의된 PA3을 GPIO, PIN 세팅

(좌) main.h에 정의된 PA3

 


2) Timer handler 오류는 타이머를 생성해서 해결 

맨 왼쪽 사진에서 Enable -> disable 로 바꿔주기

=> main.c에 htim2 생성됨 

=> 위에서 설정해줘야 할 타이머를 htim2로 설정

(좌) htim2로 설정 (우) extern 작성까지 한 최종 소스코드

=> 이때 main.h의 전역변수로 htim2가 선언되어있기에 extern 구문을 이용
cf. 전역변수를 다른 파일에서 사용하고자 할 때 extern이 필요

 

 

(5) 에러 없이 컴파일 완료 

 


1-4. 타이머 인터럽트 사용하면서 타이머 시간 조절 방법 

타이머를 사용하는데 1마이크로세컨드가되도록 설정하라는 문구
(왼) Tim2 설정 (오) Clock Configuration

 

  • 현재 Counter Period : 65535 의 의미는 0xffff
  • Clock Configuration에서 어떤 거든 다 우선 8MHz로 설정되어있음
    cf. 8MHz = 8 * 10^6 = 8000000
  • Prescaler = (10000 - 1) 로 설정해야 만으로 나눈다는 의미 
    => Counter 1을 올리기 위한 연산
  • Counter Period = (800 -1) 로 설정 
    => Counter가 하나씩 올라가는데 0~799까지 올라감
    => 이때 이 1단계가 올라가는데 클럭 1번이 뛸 때 올라가는 게 아닌 10000(만)번의 클럭이 흐르면 Counter 1 증가 
    => 만약 Counter가 800이 되면 다시 0으로 돌아오도록 설정
결론.
① Counter Period = (800 - 1)의 의미
: Counter가 0~799까지 올라가고 다시 0으로 돌아오는데 걸리는 시간은 1초라는 의미 
② Prescaler = (10000 -1)의 의미 
: Counter 1을 올리는데 걸리는 시간이고 이때 우리의 클럭은 8MHz로 되어있고 우리가 Prescaler를 (10000-1)로 설정하였기에 Counter는 800Hz 클럭 신호를 따라 1씩 증가한다.

=> 800Hz로 Counter가 증가하면서, 800번(0~799) 세면 1초가 걸린다. 
ex) 800Hz : 1초에 800번 counter 증가 

 

(1) 실제로 확인해보기

(왼) m_time 설정 (가운데) m_time을 항상 타이머 울릴 때마다 1씩 올리기 (오) 타이머가 동작하기 위해 Counter 스타트 하게하는 함수 작성

* 3번째 사진에서 TIME이 아니라 TIM임

 

1초마다 Value값이 1씩 증가함

 


2. 인터럽트 발생 시간 조절

Counter Period = 1-1로 설정하면 수행 안되어서 2-1로 변경하고 Prescaler도 8-1에서 7-1로 설정

=> 매우 빠르게 Counter값 증가함 

매뉴얼대로 설정

=> 1마이크로세컨드마다 카운트 

=> 프리스케일러 값이 커질수록 클럭의 주파수가 낮아지고, 따라서 타이머가 증가하는 속도는 느려진다

=> 만약 800Hz라면 1초에 800번의 event가 발생한다는 것이고 즉 타이머가 800번 증가한다는 의미이므로 


3. RCC 설정

(가운데) Crystal 부품 위치 (오) 우리 칩이 사용할 수 있는최대 성능의 클럭으로 설정

3-1. TIM2 수정

: 8MHz -> 72MHz로 바꾸었으므로 다음과 같이 설정

=> 1마이크로세컨드에 1 tick씩 올라감 


3-2. Counter Period를 0xFFFF로 하는 이유

 

해당 헤더파일의 init 함수 main.c에 추가

 

(좌) 무한루프 발생 (우) 해당 함수에서 ONEWIRE_DELAY 호출하여 무한루프 발생하는 것임

 

=> while문 내의 CNT가 우리가 Counter Period의 숫자값을 작게하면 그 값보다 작은 값만 발생하기에 무한루프 발생

=> 아래 사진(좌)과 같이 include 하고 다시 수행하면 정상적으로 FND 출력 

=> 이때, 우리가 클럭을 바꾸었기에 매우 빠르게 LED 숫자가 증가함

=> 아래 사진(우)과 같이 50이 아닌 450으로 바꾸고 수행하면 이전과 비슷한 속도로 증가

 


4. 온도 측정법

_DS18B20_MAX_SENSORS = 1로 설정 되어있음
만약 통신한다면 Address에 들어있는 값들이 바뀔 것임

 

4-1. 통신 여부 확인 

  • main.c 내의 Ds18b20_Init(); 호출하기 전 값들과 호출 후 값들 비교 

호출 전과 호출 후

 

4-2. 온도 정보 확인

  • ds18b20.c 내의 Ds18b20_ManualConvert함수 main.c에 넣어서 수행해보기 
  • 다음과 같이 온도센서의 프로브를 잡으면 온도가 올라가는 거 확인 가능