transmit 모드 변경
listen-only모드에서 송신 시에만 normal 모드
This commit is contained in:
@@ -168,6 +168,9 @@ WebServer server(80);
|
||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||
Preferences preferences;
|
||||
|
||||
// Forward declaration
|
||||
void IRAM_ATTR canISR();
|
||||
|
||||
QueueHandle_t canQueue;
|
||||
SemaphoreHandle_t sdMutex;
|
||||
SemaphoreHandle_t rtcMutex;
|
||||
@@ -617,8 +620,11 @@ bool setMCP2515Mode(MCP2515Mode mode) {
|
||||
case MCP_MODE_NORMAL:
|
||||
result = mcp2515.setNormalMode();
|
||||
if (result == MCP2515::ERROR_OK) {
|
||||
// 인터럽트 재활성화
|
||||
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), canISR, FALLING);
|
||||
currentMcpMode = MCP_MODE_NORMAL;
|
||||
Serial.println("✓ MCP2515 모드: NORMAL");
|
||||
Serial.println(" 송수신 모두 가능, ACK 전송");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -626,8 +632,11 @@ bool setMCP2515Mode(MCP2515Mode mode) {
|
||||
case MCP_MODE_LISTEN_ONLY:
|
||||
result = mcp2515.setListenOnlyMode();
|
||||
if (result == MCP2515::ERROR_OK) {
|
||||
// 인터럽트 재활성화
|
||||
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), canISR, FALLING);
|
||||
currentMcpMode = MCP_MODE_LISTEN_ONLY;
|
||||
Serial.println("✓ MCP2515 모드: LISTEN-ONLY");
|
||||
Serial.println(" 수신만 가능, ACK 전송 안 함");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -635,21 +644,35 @@ bool setMCP2515Mode(MCP2515Mode mode) {
|
||||
case MCP_MODE_LOOPBACK:
|
||||
result = mcp2515.setLoopbackMode();
|
||||
if (result == MCP2515::ERROR_OK) {
|
||||
// 인터럽트 재활성화
|
||||
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), canISR, FALLING);
|
||||
currentMcpMode = MCP_MODE_LOOPBACK;
|
||||
Serial.println("✓ MCP2515 모드: LOOPBACK");
|
||||
Serial.println(" 자가 테스트 모드");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCP_MODE_TRANSMIT:
|
||||
// Transmit mode: Normal 모드와 동일하게 동작
|
||||
// (라이브러리 제약으로 인해 레지스터 직접 접근 불가)
|
||||
// 송신 위주로 사용하되, 수신도 가능한 모드
|
||||
result = mcp2515.setNormalMode();
|
||||
// TRANSMIT 모드: Listen-Only 기반
|
||||
// 평상시에는 Listen-Only로 동작하여 ACK를 보내지 않음
|
||||
// 송신이 필요할 때만 일시적으로 Normal 모드로 전환
|
||||
result = mcp2515.setListenOnlyMode();
|
||||
if (result == MCP2515::ERROR_OK) {
|
||||
// 인터럽트는 비활성화 (수신 처리하지 않음)
|
||||
detachInterrupt(digitalPinToInterrupt(CAN_INT_PIN));
|
||||
|
||||
// 수신 버퍼를 비움
|
||||
struct can_frame frame;
|
||||
while (mcp2515.readMessage(&frame) == MCP2515::ERROR_OK) {
|
||||
// 버퍼만 비움
|
||||
}
|
||||
|
||||
currentMcpMode = MCP_MODE_TRANSMIT;
|
||||
Serial.println("✓ MCP2515 모드: TRANSMIT (Normal mode base)");
|
||||
Serial.println(" ※ 송신 위주 사용, 수신 데이터는 로깅하지 않음");
|
||||
Serial.println("✓ MCP2515 모드: TRANSMIT-ONLY");
|
||||
Serial.println(" 기본: Listen-Only (ACK 안 함)");
|
||||
Serial.println(" 송신 시: 일시적으로 Normal 전환");
|
||||
Serial.println(" 수신 인터럽트: 비활성화");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -659,6 +682,41 @@ bool setMCP2515Mode(MCP2515Mode mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CAN 송신 헬퍼 함수 (TRANSMIT 모드 자동 처리)
|
||||
// ========================================
|
||||
|
||||
MCP2515::ERROR sendCANMessage(struct can_frame* frame) {
|
||||
MCP2515::ERROR result;
|
||||
|
||||
// TRANSMIT 모드일 때만 특별 처리
|
||||
if (currentMcpMode == MCP_MODE_TRANSMIT) {
|
||||
// 1. 일시적으로 Normal 모드로 전환
|
||||
result = mcp2515.setNormalMode();
|
||||
if (result != MCP2515::ERROR_OK) {
|
||||
Serial.println("✗ TRANSMIT 모드: Normal 전환 실패");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 메시지 송신
|
||||
result = mcp2515.sendMessage(frame);
|
||||
|
||||
// 3. 즉시 Listen-Only 모드로 복귀
|
||||
mcp2515.setListenOnlyMode();
|
||||
|
||||
// 4. 수신 버퍼 비우기 (전환 중 수신된 데이터)
|
||||
struct can_frame dummy;
|
||||
while (mcp2515.readMessage(&dummy) == MCP2515::ERROR_OK) {
|
||||
// 버퍼만 비움
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
// 다른 모드에서는 바로 송신
|
||||
return mcp2515.sendMessage(frame);
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CAN 인터럽트 및 수신 함수
|
||||
// ========================================
|
||||
@@ -678,15 +736,6 @@ void canRxTask(void* parameter) {
|
||||
for (;;) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
// Transmit 모드일 때는 수신 데이터를 처리하지 않음
|
||||
if (currentMcpMode == MCP_MODE_TRANSMIT) {
|
||||
// MCP2515 버퍼만 비우고 처리는 건너뜀
|
||||
while (mcp2515.readMessage(&frame) == MCP2515::ERROR_OK) {
|
||||
// 버퍼만 비움
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 한 번에 여러 메시지를 읽어서 처리 속도 향상
|
||||
int readCount = 0;
|
||||
while (mcp2515.readMessage(&frame) == MCP2515::ERROR_OK && readCount < 20) {
|
||||
@@ -897,7 +946,7 @@ void txTask(void* parameter) {
|
||||
frame.can_dlc = txMessages[i].dlc;
|
||||
memcpy(frame.data, txMessages[i].data, 8);
|
||||
|
||||
if (mcp2515.sendMessage(&frame) == MCP2515::ERROR_OK) {
|
||||
if (sendCANMessage(&frame) == MCP2515::ERROR_OK) {
|
||||
txMessages[i].lastSent = now;
|
||||
totalTxCount++;
|
||||
}
|
||||
@@ -934,7 +983,7 @@ void sequenceTask(void* parameter) {
|
||||
frame.can_dlc = step->dlc;
|
||||
memcpy(frame.data, step->data, 8);
|
||||
|
||||
MCP2515::ERROR result = mcp2515.sendMessage(&frame);
|
||||
MCP2515::ERROR result = sendCANMessage(&frame);
|
||||
if (result == MCP2515::ERROR_OK) {
|
||||
totalTxCount++;
|
||||
Serial.printf(" [Seq] Step %d/%d: ID=0x%X, DLC=%d, Delay=%dms - OK\n",
|
||||
@@ -1118,7 +1167,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
|
||||
int mode = message.substring(modeStart, modeEnd).toInt();
|
||||
|
||||
if (mode >= 0 && mode <= 2) {
|
||||
if (mode >= 0 && mode <= 3) { // 0~3으로 확장 (TRANSMIT 모드 포함)
|
||||
setMCP2515Mode((MCP2515Mode)mode);
|
||||
}
|
||||
|
||||
|
||||
10
index.h
10
index.h
@@ -701,10 +701,10 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
<div class="control-row">
|
||||
<label for="mcp-mode">MCP2515 Mode:</label>
|
||||
<select id="mcp-mode">
|
||||
<option value="0" selected>Normal</option>
|
||||
<option value="1">Listen-Only</option>
|
||||
<option value="2">Loopback</option>
|
||||
<option value="3">Transmit (TX Focus)</option>
|
||||
<option value="0" selected>Normal (TX/RX + ACK)</option>
|
||||
<option value="1">Listen-Only (RX only, no ACK)</option>
|
||||
<option value="2">Loopback (Self-test)</option>
|
||||
<option value="3">Transmit Only (no ACK, auto mode switch)</option>
|
||||
</select>
|
||||
<button onclick="setMcpMode()">Apply</button>
|
||||
<span id="mode-status" style="color: #11998e; font-size: 0.85em; font-weight: 600;"></span>
|
||||
@@ -768,7 +768,7 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
let messageOrder = [];
|
||||
let lastMessageData = {};
|
||||
const speedNames = {0: '125K', 1: '250K', 2: '500K', 3: '1M'};
|
||||
const modeNames = {0: 'NORMAL', 1: 'LISTEN-ONLY', 2: 'LOOPBACK', 3: 'TRANSMIT'};
|
||||
const modeNames = {0: 'NORMAL (TX/RX+ACK)', 1: 'LISTEN-ONLY (RX)', 2: 'LOOPBACK', 3: 'TRANSMIT-ONLY (TX)'};
|
||||
let currentLoggingFile = '';
|
||||
let commentingFile = '';
|
||||
let hasInitialSync = false; // 초기 동기화 완료 여부
|
||||
|
||||
Reference in New Issue
Block a user