You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

764 lines
22 KiB

#include "owi.h"
#include "delay.h"
#include <string.h>
#include "uart.h"
/**
* 함수명: OWI_EnablePower
* 목적: 1-Wire 장치의 전원을 켠다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* - MCU 포트 P7의 1번 핀(P7.1)을 출력 모드로 설정하고 논리 HIGH(_02_Pn1_OUTPUT_1)로 설정하여
* 1-Wire 장치에 전원을 공급한다.
*/
void OWI_EnablePower(void) {
P7 = _02_Pn1_OUTPUT_1;
}
/**
* 함수명: OWI_DisablePower
* 목적: 1-Wire 장치의 전원을 끈다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* - MCU 포트 P7의 1번 핀(P7.1)을 출력 모드로 설정하고 논리 LOW(_00_Pn1_OUTPUT_0)로 설정하여
* 1-Wire 장치에 공급되는 전원을 차단한다.
*/
void OWI_DisablePower(void) {
P7 = _00_Pn1_OUTPUT_0;
}
/**
* 함수명: GPIO_Clear
* 목적: 1-Wire 통신에 사용하는 GPIO(P70)를 초기화하고 Low 상태로 설정한다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* - OWI_PORT_P 레지스터에서 해당 핀(OWI_PIN_MASK) 비트를 0으로 설정하여 P70을 Low로 만든다.
* - OWI_PORT_PM 레지스터에서 해당 핀 비트를 0으로 설정하여 P70을 출력 모드로 설정한다.
* - 결과적으로 P70 핀은 출력 모드로 Low 상태가 된다.
*/
void GPIO_Clear(void) {
OWI_PORT_P &= ~OWI_PIN_MASK; // P70 = 0 (Low)
OWI_PORT_PM &= ~OWI_PIN_MASK; // P70 출력 모드
}
/**
* 함수명: GPIO_Input
* 목적: 1-Wire 통신에 사용하는 GPIO(P70)를 입력 모드로 설정한다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* - OWI_PORT_PM 레지스터에서 해당 핀(OWI_PIN_MASK) 비트를 1로 설정하여 P70을 입력 모드(High-Z)로 만든다.
* - 출력 신호를 끄고 외부 장치로부터 신호를 읽을 준비를 한다.
*/
void GPIO_Input(void) {
OWI_PORT_PM |= OWI_PIN_MASK; // P70 입력 모드 (High-Z)
}
/**
* 함수명: GPIO_Read
* 목적: 1-Wire 통신에 사용하는 GPIO(P70)의 현재 상태를 읽는다.
*
* 매개변수: 없음
*
* 반환값:
* - 1 : P70 핀이 High 상태일 때
* - 0 : P70 핀이 Low 상태일 때
*
* 동작 방식:
* - OWI_PORT_P 레지스터에서 해당 핀(OWI_PIN_MASK) 비트를 확인한다.
* - 비트가 1이면 High, 0이면 Low로 판단하여 정수값으로 반환한다.
* - 외부 장치에서 보내는 신호를 읽거나, 현재 GPIO 상태를 확인할 때 사용된다.
*/
int GPIO_Read(void) {
return (OWI_PORT_P & OWI_PIN_MASK) ? 1 : 0;
}
/**
* 함수명: OWI_Init
* 목적: 1-Wire 통신을 시작하기 위해 GPIO 및 통신 속도를 초기화한다.
*
* 매개변수:
* - bit_time_us : 1비트 전송에 걸리는 시간(마이크로초 단위)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. bit_period_us 전역 변수에 비트 전송 시간을 저장.
* 2. OWI_PORT_POM 레지스터에서 해당 핀(OWI_PIN_MASK)을 Open-drain(n-channel) 모드로 설정.
* 3. OWI_PORT_PU 레지스터에서 해당 핀의 내부 풀업 저항 활성화.
* 4. 초기 상태에서 GPIO를 입력 모드로 설정하여 외부 신호를 기다리는 상태로 대기.
*
*/
void OWI_Init(uint32_t bit_time_us) {
bit_period_us = bit_time_us;
OWI_PORT_POM |= OWI_PIN_MASK; // Open-drain (n-channel)
OWI_PORT_PU |= OWI_PIN_MASK; // 내부 풀업 활성화
GPIO_Input(); // 초기엔 입력으로 대기
}
// ----------------------------------------
// OWI Start/Stop/Secure
// ----------------------------------------
/**
* 함수명: OWI_Start
* 목적: 1-Wire 통신에서 Start 신호를 발생시켜 통신을 시작한다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. GPIO_Clear() 호출: P70 핀을 Low 상태로 설정하여 Start 신호를 준비.
* 2. delay_us(TSTART_HOLD): Start 신호를 일정 시간 유지.
* 3. GPIO_Input() 호출: 핀을 입력 모드(High-Z)로 전환하여 외부 장치가 반응하도록 대기.
* 4. delay_us(TBIT / 2): 반비트 시간만큼 대기하여 1-Wire 타이밍 맞춤.
*
*/
void OWI_Start(void)
{
GPIO_Clear();
delay_us(TSTART_HOLD);
GPIO_Input();
delay_us(TBIT / 2);
}
/**
* 함수명: OWI_Stop
* 목적: 1-Wire 통신을 종료하고 통신 라인을 정리한다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. GPIO_Input() 호출: 핀을 입력 모드(High-Z)로 설정하여 초기 상태로 대기.
* 2. delay_us(TSTOP_LOW): Stop 조건을 만족시키기 위해 일정 시간 대기.
* 3. delay_us(TIDLE): 통신 라인을 안정화시키기 위해 추가 지연.
* 4. GPIO_Clear() 호출: 핀을 Low로 초기화하여 다음 통신 준비.
*
*/
void OWI_Stop(void)
{
GPIO_Input();
delay_us(TSTOP_LOW);
delay_us(TIDLE);
GPIO_Clear();
}
/**
* 함수명: OWI_SecureStop
* 목적: 1-Wire 통신 종료 시 라인을 안전하게 토글하여 슬레이브가 확실히 종료 상태를 인식하도록 한다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. GPIO_Clear() 호출 후 SECURE_HIGH 시간만큼 지연: 라인을 Low 상태로 초기화.
* 2. SECURE_TOGGLE_COUNT만큼 반복:
* - GPIO_Input()로 라인을 High-Z 상태로 설정 후 SECURE_TOGGLE_HIGH 시간 대기.
* - GPIO_Clear()로 라인을 Low 상태로 설정 후 SECURE_TOGGLE_LOW 시간 대기.
* - 이 과정을 통해 슬레이브가 안전하게 라인 종료를 감지.
* 3. GPIO_Input() → SECURE_HIGH 지연 → GPIO_Clear() → TSTART_HOLD 지연 → GPIO_Input() 호출:
* - 라인을 초기 상태로 복귀시켜 다음 통신 준비 완료.
*
*/
void OWI_SecureStop(void)
{
int i;
GPIO_Clear();
delay_us(SECURE_HIGH);
for (i = 0; i < SECURE_TOGGLE_COUNT; i++) {
GPIO_Input();
delay_us(SECURE_TOGGLE_HIGH);
GPIO_Clear();
delay_us(SECURE_TOGGLE_LOW);
}
GPIO_Input();
delay_us(SECURE_HIGH);
GPIO_Clear();
delay_us(TSTART_HOLD);
GPIO_Input();
}
// ----------------------------------------
// OWI Bit/Byte Write & Read
// ----------------------------------------
/**
* 함수명: OWI_WriteBit
* 목적: 1-Wire 통신 라인을 통해 단일 비트(bit)를 송신한다.
*
* 매개변수:
* - bit : 전송할 비트 값 (0 또는 1)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. 전송할 비트에 따라 Low 상태 유지 시간(t_low)을 결정:
* - bit가 1이면 TLOW_1, 0이면 TLOW_0
* 2. t_high = TBIT - t_low 계산: 비트 프레임에서 High 유지 시간 결정.
* 3. GPIO_Input() 호출: 라인을 풀업 상태(High-Z)로 유지.
* 4. delay_us(t_high): High 상태 유지.
* 5. GPIO_Clear() 호출: 라인을 Low 상태로 드라이브.
* 6. delay_us(t_low): Low 상태 유지.
*
*/
void OWI_WriteBit(int bit)
{
uint32_t t_low = bit ? TLOW_1 : TLOW_0;
uint32_t t_high = TBIT - t_low;
GPIO_Input(); // 풀업 상태 유지
delay_us(t_high); // High 유지
GPIO_Clear(); // Low로 드라이브
delay_us(t_low); // Low 시간 유지
}
/**
* 함수명: OWI_WriteByte
* 목적: 1-Wire 통신 라인을 통해 1바이트 데이터를 전송한다.
*
* 매개변수:
* - data : 전송할 1바이트 데이터(uint8_t)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. 최상위 비트(MSB)부터 최하위 비트(LSB)까지 반복:
* - 각 비트를 OWI_WriteBit() 함수를 통해 송신.
* - (data >> i) & 0x01 연산으로 i번째 비트 추출.
* 2. 모든 8비트를 전송한 후 GPIO_Input() 호출:
* - 라인을 High-Z 상태로 전환하여 다음 통신 준비.
*
*/
void OWI_WriteByte(uint8_t data)
{
int i;
for (i = 7; i >= 0; i--) {
OWI_WriteBit((data >> i) & 0x01);
}
GPIO_Input();
}
/**
* 함수명: OWI_ReadBit
* 목적: 1-Wire 통신 라인에서 단일 비트를 읽는다.
*
* 매개변수: 없음
*
* 반환값:
* - 0 또는 1 : 읽은 비트 값
* - 0xFF : 타임아웃 발생 시 에러 값
*
* 동작 방식:
* 1. GPIO_Read()를 사용하여 라인이 High가 될 때까지 대기:
* - 최대 500us까지 대기(timeout).
* - 타임아웃 시 UART로 오류 메시지 전송 후 0xFF 반환.
* 2. delay_us(50) 호출하여 비트 중앙 위치로 대기.
* 3. GPIO_Read()로 비트 값 판독.
* 4. delay_us(30)으로 나머지 비트 시간 동안 대기.
* 5. 판독한 비트 값을 반환.
*
*/
uint8_t OWI_ReadBit(void)
{
uint8_t bit;
int timeout = 500;
while (!(GPIO_Read()) && timeout-- > 0) {
delay_us(1);
}
if (timeout <= 0) {
uart_send_string("OWI Timeout\r\n");
return 0xFF;
}
delay_us(50);
bit = GPIO_Read();
delay_us(30);
return bit;
}
/**
* 함수명: OWI_ReadByte
* 목적: 1-Wire 통신 라인에서 1바이트 데이터를 읽는다.
*
* 매개변수: 없음
*
* 반환값:
* - 읽은 1바이트 데이터(uint8_t)
*
* 동작 방식:
* 1. 최상위 비트(MSB)부터 최하위 비트(LSB)까지 반복:
* - OWI_ReadBit() 함수를 호출하여 1비트씩 읽는다.
* - 읽은 비트를 적절히 시프트하여 data 변수에 저장.
* 2. 모든 8비트를 읽은 후 data 반환.
*
*/
uint8_t OWI_ReadByte(void)
{
uint8_t data = 0;
int i;
for (i = 7; i >= 0; i--) {
data |= (OWI_ReadBit() << i);
}
return data;
}
/**
* 함수명: OWI_T_ReadBytesAndPrint
* 목적: 1-Wire 통신으로 지정한 길이만큼 데이터를 읽고, UART로 형식화하여 출력한다.
*
* 매개변수:
* - length : 읽을 데이터 바이트 수
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1. buf 배열에 length만큼 OWI_ReadByte() 호출하여 1바이트씩 읽어 저장.
* 2. 첫 번째 바이트(buf[0])를 16진수 2자리 문자열로 변환하여 UART 전송.
* 3. 그 이후 바이트들은 두 개씩 묶어서 16진수 4자리 문자열로 변환 후 UART 전송:
* - delay(10000) 호출하여 출력 간 간격을 둠.
* 4. UART 출력은 sprintf → strcpy → uart_send_string 순으로 처리.
*
* 참고:
* - buf[0]는 별도로 출력하고, 이후 바이트들은 2바이트 단위로 묶어 출력.
* - delay를 통해 슬레이브와 UART 전송 간 타이밍을 확보.
* - 1-Wire 데이터를 확인하거나 디버깅용으로 사용되는 함수.
*/
void OWI_T_ReadBytesAndPrint(int length)
{
uint8_t buf[129];
int i;
char uart_buf[8];
char tmp_buf[8];
uint8_t va0, va1;
for (i = 0; i < length; i++) {
buf[i] = OWI_ReadByte();
}
sprintf(uart_buf, "%02X ", buf[0]);
strcpy(tmp_buf, uart_buf);
uart_send_string(tmp_buf);
for (i = 1; i < length; i+=2) {
va0 = buf[i];
va1 = buf[i+1];
delay(10000);
sprintf(uart_buf, "%02X%02X ", va0, va1);
strcpy(tmp_buf, uart_buf);
uart_send_string(tmp_buf);
delay(10000);
}
}
/**
* 함수명: OWI_A_CommandMode
* 목적: 1-Wire 장치에서 ADC 데이터 및 명령어(CMD)를 처리하고 결과를 UART로 출력한다.
*
* 매개변수:
* - tx_data : 사용자 전송 데이터 포인터 (3바이트)
* - tx_len : 사용자 전송 데이터 길이
* - id : 장치 ID
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) ADC 읽기
* - ADC_ReadAndSend_UART() 호출하여 ADC 데이터를 읽음.
* - g_adc_bytes 배열을 읽고 2자리 소수점 형식으로 line 배열에 저장.
* - ADC 채널 수 불일치 시 "Err:adc_count" 출력 후 종료.
*
* 2) 1-Wire 장치 전원 켜기
* - OWI_EnablePower() 호출.
* - 전원 안정화를 위해 7ms 지연.
*
* 3) 기본 명령(CMD) 전송 및 안전한 읽기
* - CMD_LIST에 정의된 6개의 4바이트 명령을 순차적으로 전송.
* - 각 명령 전/후에 OWI_SecureStop() 호출하여 통신 라인을 초기화.
* - 각 명령 실행 후 read_address(0x51)로 데이터를 읽음.
* - 읽은 데이터가 모두 0xFF일 경우 최대 OWI_MAX_RETRY만큼 재시도.
* - 읽은 Rx 데이터에서 2번째, 3번째 바이트를 line 배열에 16진수로 추가.
*
* 4) 사용자 CMD 처리 (tx_data 존재 시)
* - tx_len가 3바이트인 경우 ID를 포함한 write 후 read 수행.
* - Rx 데이터 모두 0xFF일 경우 OWI_MAX_RETRY 재시도.
* - 정상 데이터 수신 시 line 배열에 2번째, 3번째 바이트 추가.
* - tx_data가 없으면 "0000"을 line 배열에 추가.
*
* 5) UART 출력
* - 완성된 line 배열 끝에 CRLF 추가 후 uart_send_string()로 전송.
*
* 6) 마무리
* - delay(10000) 후 OWI_DisablePower() 호출하여 장치 전원 차단.
*
* 참고:
* - OWI_SecureStop() 및 delay_us()를 통해 1-Wire 통신 타이밍과 안정성을 확보.
* - g_adc_bytes, RAM_BYTES, OWI_MAX_RETRY 등의 상수 및 전역 변수 활용.
* - UART로 출력되는 형식은 ADC값, 각 CMD 결과, 사용자 CMD 결과가 쉼표로 구분됨.
*/
#define OWI_MAX_RETRY 2 // 재시도 2회
#define OWI_RECOVERY_MIN_US 500 // datasheet 기준 최소 recovery 시간
/**
* 함수명: OWI_Diagnostic
* 목적: 1-Wire 장치에서 진단용 명령어를 전송하고 결과를 UART로 출력한다.
*
* 매개변수:
* - id : 장치 ID (사용되지 않지만 인터페이스 일관성 유지)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) CMD_LIST에 정의된 10개의 4바이트 진단 명령어를 순차적으로 전송.
* - OWI_SecureStop() 호출로 통신 라인 초기화.
* - 각 명령 전송 후 OWI_Stop() 호출.
* - OWI_RECOVERY_MIN_US 동안 지연하여 장치 준비 시간 확보.
*
* 2) 각 명령어 수행 후 read_address(0x51)로 데이터를 읽음.
* - Rx 배열 초기화(0xFF) 후 OWI_ReadByte()로 데이터 수신.
* - 읽은 데이터가 모두 0xFF일 경우 최대 OWI_MAX_RETRY만큼 재시도.
*
* 3) 정상 데이터 수신 시 rx[1], rx[2] 바이트를 16진수로 line 배열에 추가.
* - 마지막 명령어가 아니면 콤마(,) 추가.
*
* 4) UART 출력
* - line 배열 끝에 CRLF 추가 후 uart_send_string()으로 전송.
*
* 참고:
* - OWI_SecureStop() 및 delay_us()를 통해 1-Wire 통신 안정성을 확보.
* - 이 함수는 장치의 상태 진단 및 디버깅용으로 사용됨.
*/
void OWI_Diagnostic(uint8_t id)
{
uint8_t CMD_LIST[10][4] = {
{0x50,0x2E,0x01,0x00}, // BR
{0x50,0x2E,0x00,0x00}, // BR_AZ
{0x50,0x2E,0x02,0x00}, // T_RAW
{0x50,0x2E,0x03,0x00}, // Y_data
{0x50,0x2E,0x21,0x00}, // BR_AOUT
{0x50,0x2E,0x04,0x00},
{0x50,0x2E,0x05,0x00},
{0x50,0x2E,0x07,0x00},
{0x50,0x2E,0x19,0x00},
{0x50,0x2E,0x0B,0x00}
};
char line[128];
size_t n = 0;
uint8_t rx[RAM_BYTES];
int i, j, retry, all_ff;
float v;
uint8_t read_address = 0x51;
// ===== 3) CMD 전송 및 안전한 읽기 =====
for (j = 0; j < 10; j++) {
OWI_SecureStop();
for (i = 0; i < 4; i++) OWI_WriteByte(CMD_LIST[j][i]);
OWI_Stop();
// CMD → read 회복 시간
delay_us(OWI_RECOVERY_MIN_US);
// Rx 초기화
for (i = 0; i < RAM_BYTES; i++) rx[i] = 0xFF;
for (retry = 0; retry <= OWI_MAX_RETRY; retry++) {
// read 전 충분한 recovery 확보
delay_us(OWI_RECOVERY_MIN_US);
OWI_SecureStop();
OWI_WriteByte(read_address);
for (i = 0; i < RAM_BYTES; i++) rx[i] = OWI_ReadByte();
OWI_Stop();
all_ff = 1;
for (i = 0; i < RAM_BYTES; i++) {
if (rx[i] != 0xFF) { all_ff = 0; break; }
}
if (!all_ff) break; // 정상 데이터 수신
if (retry == OWI_MAX_RETRY) { // 모든 재시도 실패
OWI_DisablePower();
return;
}
}
// 데이터 추가
n += sprintf(&line[n], "%02X%02X", rx[1], rx[2]);
// 마지막이 아닐 때만 콤마 추가
if (j < 9) {
line[n++] = ',';
}
}
// ===== 5) UART 출력 =====
line[n++] = '\r';
line[n++] = '\n';
line[n] = '\0';
uart_send_string(line);
delay(10000);
}
/**
* 함수명: OWI_disable
* 목적: 1-Wire 장치 전원을 끄고, UART로 상태를 알린다.
*
* 매개변수: 없음
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) OWI_DisablePower() 호출하여 1-Wire 장치 전원 차단.
* 2) UART로 "51" 문자열과 CRLF 전송하여 장치가 종료되었음을 표시.
*
* 참고:
* - 장치 종료 후 외부 장치나 사용자에게 상태 알림용으로 UART 출력.
*/
void OWI_disable()
{
OWI_DisablePower();
uart_send_string("51\r\n");
}
/**
* 함수명: OWI_T_CommandMode
* 목적: 1-Wire 장치에 명령어를 전송하고, UART로 완료 상태를 출력한다.
*
* 매개변수:
* - tx_data : 전송할 명령 데이터 배열
* - tx_len : 전송할 명령 데이터 길이
* - id : 1-Wire 장치 ID (슬레이브 주소)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) 1-Wire 장치 전원 켜기
* - OWI_EnablePower() 호출
* - 전원 안정화를 위해 7ms 지연
*
* 2) 1-Wire 초기화
* - OWI_Init() 호출하여 통신 비트 주기 설정
*
* 3) 명령 전송 (Write sequence)
* - OWI_SecureStop() 호출로 통신 라인 초기화
* - 슬레이브 주소(id << 1)를 전송 (쓰기 모드)
* - tx_data 배열에 있는 명령 데이터를 순차적으로 전송
* - OWI_Stop() 호출하여 쓰기 종료
*
* 4) UART 출력
* - "51" 문자열 전송하여 명령 전송 완료 상태 알림
*
* 참고:
* - 이 함수는 단순히 명령어 전송만 수행하며, 데이터 읽기는 수행하지 않는다.
* - OWI_SecureStop()와 OWI_Stop()을 사용해 1-Wire 통신 안정성을 확보.
*/
void OWI_T_CommandMode(const uint8_t *tx_data, uint8_t tx_len, uint8_t id)
{
uint8_t rx[3] = {0};
char uart_buf[16];
int i;
OWI_EnablePower();
delay_us(7000); // Power-on delay
OWI_Init(OWI_BIT_PERIOD_US);
// Write sequence (슬레이브 주소와 명령 전송)
OWI_SecureStop(); // 통신 준비
OWI_WriteByte(id << 1); // 슬레이브 write 주소
for (i = 0; i < tx_len; i++) {
OWI_WriteByte(tx_data[i]); // 명령 전송
}
OWI_Stop(); // 쓰기 종료
uart_send_string("51\r\n");
}
/**
* 함수명: OWI_CommandMode
* 목적: 1-Wire 장치에 명령어를 전송하고, UART로 완료 상태를 출력한다.
*
* 매개변수:
* - tx_data : 전송할 명령 데이터 배열
* - tx_len : 전송할 명령 데이터 길이
* - id : 1-Wire 장치 ID (슬레이브 주소)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) 명령 전송 (Write sequence)
* - OWI_SecureStop() 호출로 통신 라인 초기화
* - 슬레이브 주소(id << 1)를 전송 (쓰기 모드)
* - tx_data 배열에 있는 명령 데이터를 순차적으로 전송
* - OWI_Stop() 호출하여 쓰기 종료
*
* 2) UART 출력
* - "51" 문자열 전송하여 명령 전송 완료 상태 알림
*
* 참고:
* - 전원 켜기/통신 초기화 단계는 포함되어 있지 않음
* - 이 함수는 단순히 명령어 전송만 수행하며, 데이터 읽기는 수행하지 않는다
* - OWI_SecureStop()와 OWI_Stop()을 사용해 1-Wire 통신 안정성을 확보
*/
void OWI_CommandMode(const uint8_t *tx_data, uint8_t tx_len, uint8_t id)
{
uint8_t rx[3] = {0};
char uart_buf[16];
int i;
// Write sequence (슬레이브 주소와 명령 전송)
OWI_SecureStop(); // 통신 준비
OWI_WriteByte(id << 1); // 슬레이브 write 주소
for (i = 0; i < tx_len; i++) {
OWI_WriteByte(tx_data[i]); // 명령 전송
}
OWI_Stop(); // 쓰기 종료
uart_send_string("51\r\n");
}
/**
* 함수명: OWI_ReadBytesAndPrint
* 목적: 1-Wire 장치에서 지정된 길이만큼 데이터를 읽고, UART로 출력한다.
*
* 매개변수:
* - length : 읽을 바이트 수
* - id : 1-Wire 장치 ID (슬레이브 주소)
*
* 반환값: 없음 (void)
*
* 동작 방식:
* 1) 읽기 시작
* - OWI_SecureStop() 호출로 통신 라인 초기화
* - (id << 1) | 1 전송하여 슬레이브 읽기 모드 설정
*
* 2) 지정된 length만큼 OWI_ReadByte()로 데이터 읽기
* - 읽은 데이터는 buf 배열에 저장
*
* 3) UART 출력
* - buf[0] 단독 출력
* - 이후 1번부터는 두 바이트씩 페어로 묶어 출력
* - 마지막 바이트가 홀수이면 단독 출력
* - 각 출력 전후에 delay(10000) 호출 (UART 전송 안정성 확보)
* - 출력 포맷: 16진수 문자열
* - 마지막에 CRLF("\r\n") 추가
*
* 참고:
* - UART 출력 시 임시 버퍼(uart_buf, tmp_buf)를 사용
* - delay를 통해 데이터 안정성 및 가독성 확보
*/
void OWI_ReadBytesAndPrint(int length, uint8_t id)
{
uint8_t buf[600];
int i;
char uart_buf[8];
char tmp_buf[8];
uint8_t va0, va1;
OWI_SecureStop();
OWI_WriteByte((id << 1) | 1);
for (i = 0; i < length; i++) {
buf[i] = OWI_ReadByte();
}
sprintf(uart_buf, "%02X ", buf[0]);
strcpy(tmp_buf, uart_buf);
uart_send_string(tmp_buf);
for (i = 1; i < length; i += 2) {
va0 = buf[i];
if (i + 1 < length) {
// 완전한 페어
va1 = buf[i + 1];
delay(10000);
sprintf(uart_buf, "%02X%02X ", va0, va1);
strcpy(tmp_buf, uart_buf);
uart_send_string(tmp_buf);
delay(10000);
} else {
// 마지막 1바이트가 남은 경우 단독 출력
delay(10000);
sprintf(uart_buf, "%02X", va0);
strcpy(tmp_buf, uart_buf);
uart_send_string(tmp_buf);
delay(10000);
}
}
uart_send_string("\r\n");
}