/*
  NEXTION → ARDUINO DIAGNOSTIC RECEIVER
  - In ra Serial Monitor (115200) khi nhận:
    1) Khung nhị phân: A5 A5 A5 [page][type][index][d0][d1]
       -> Log: [BIN] page,type,index,d0,d1,value
    2) CSV: "CT1,<n0>,<n1>,<n2>."
       -> Log: [CSV] n0,n1,n2
  Chọn cổng Nextion:
    - Với Mega/ESP32/STM32: #define USE_HW_SERIAL1
    - Với UNO/Nano: comment dòng USE_HW_SERIAL1, dùng SoftwareSerial(10,11)
*/
// ====== CHỌN CỔNG NEXTION ======
#define USE_HW_SERIAL1   // <- Bỏ comment nếu bạn có Serial1 (Mega/ESP32/STM32)
#ifdef USE_HW_SERIAL1
  #define NX Serial1
#else
  #include <SoftwareSerial.h>
  SoftwareSerial NX(10, 11);  // RX, TX cho UNO/Nano
#endif
#define PC Serial  // Serial Monitor
// ====== HỖ TRỢ IN HEX GỌN ======
static void printHex2(uint8_t b) {
  if (b < 16) PC.print('0');
  PC.print(b, HEX);
}
// ====== BỘ NHẬN KHUNG NHỊ PHÂN A5 A5 A5 + 5 BYTE ======
struct Frame5 { uint8_t page, type, index, d0, d1; };
static uint8_t  a5count = 0;   // đếm A5
static uint8_t  pay_i   = 0;   // chỉ số byte payload
static Frame5   paybuf;        // buffer 5 byte
void processBinaryByte(uint8_t b) {
  // Đồng bộ 3 byte A5
  if (a5count < 3) {
    if (b == 0xA5) {
      if (++a5count == 3) pay_i = 0; // chuẩn bị nhận 5 byte
    } else {
      a5count = 0; // mất sync
    }
    return;
  }
  // Nhận 5 byte payload
  reinterpret_cast<uint8_t*>(&paybuf)[pay_i++] = b;
  if (pay_i >= 5) {
    // Hoàn tất 1 khung: log ra Serial
    uint16_t value = (uint16_t)paybuf.d0 | ((uint16_t)paybuf.d1 << 8);
    PC.print(F("[BIN] page=0x"));  printHex2(paybuf.page);
    PC.print(F(" type=0x"));       printHex2(paybuf.type);
    PC.print(F(" index=0x"));      printHex2(paybuf.index);
    PC.print(F(" d0=0x"));         printHex2(paybuf.d0);
    PC.print(F(" d1=0x"));         printHex2(paybuf.d1);
    PC.print(F("  value="));       PC.println(value);
    // Reset chờ khung mới
    a5count = 0;
    pay_i   = 0;
  }
}
// ====== BỘ NHẬN CSV: "CT1,<n0>,<n1>,<n2>." ======
// Trạng thái đơn giản để tránh nhầm với nhị phân
enum CSVState { CSV_IDLE, CSV_C, CSV_CT, CSV_CT1, CSV_COLLECT };
static CSVState csv_state = CSV_IDLE;
static char csv_buf[64];
static uint8_t csv_len = 0;
void resetCSV() {
  csv_state = CSV_IDLE;
  csv_len = 0;
}
void processCSVByte(uint8_t b) {
  char c = (char)b;
  switch (csv_state) {
    case CSV_IDLE:   csv_state = (c=='C') ? CSV_C : CSV_IDLE; break;
    case CSV_C:      csv_state = (c=='T') ? CSV_CT : CSV_IDLE; break;
    case CSV_CT:     csv_state = (c=='1') ? CSV_CT1 : CSV_IDLE; break;
    case CSV_CT1:    csv_state = (c==',') ? CSV_COLLECT : CSV_IDLE;
                     if (csv_state == CSV_COLLECT) { csv_len = 0; csv_buf[csv_len++]='C'; csv_buf[csv_len++]='T'; csv_buf[csv_len++]='1'; csv_buf[csv_len++]=','; }
                     break;
    case CSV_COLLECT:
      if (csv_len < sizeof(csv_buf)-1) csv_buf[csv_len++] = c;
      if (c == '.') {
        csv_buf[csv_len] = '\0';
        // csv_buf bây giờ có dạng "CT1,<n0>,<n1>,<n2>."
        // Parse nhanh:
        // Bỏ '.' cuối
        if (csv_len && csv_buf[csv_len-1]=='.') csv_buf[csv_len-1] = '\0';
        // Bỏ prefix "CT1,"
        char *p = csv_buf + 4;
        char *t0 = strtok(p, ",");
        char *t1 = strtok(NULL, ",");
        char *t2 = strtok(NULL, ",");
        if (t0 && t1 && t2) {
          int n0 = atoi(t0);
          int n1 = atoi(t1);
          int n2 = atoi(t2);
          PC.print(F("[CSV] n0=")); PC.print(n0);
          PC.print(F(" n1="));     PC.print(n1);
          PC.print(F(" n2="));     PC.println(n2);
        } else {
          PC.println(F("[CSV] Parse error"));
        }
        resetCSV();
      }
      break;
  }
}
// ====== BƠM DỮ LIỆU TỪ NEXTION SANG 2 BỘ NHẬN ======
void pumpNextion() {
  while (NX.available()) {
    uint8_t b = NX.read();
    // Luồng nhị phân (A5 A5 A5 ...):
    processBinaryByte(b);
    // Luồng CSV (chỉ hoạt động nếu thấy 'CT1,'):
    processCSVByte(b);
  }
}
// ====== SETUP/LOOP ======
void setup() {
  PC.begin(115200);
  #ifdef USE_HW_SERIAL1
    NX.begin(9600);
  #else
    NX.begin(9600);
  #endif
  PC.println(F("Ready. Press START on Nextion."));
  PC.println(F("Expect either:"));
  PC.println(F("  [BIN] page,type,index,d0,d1,value   (for printh A5 A5 A5 ...)"));
  PC.println(F("  [CSV] n0,n1,n2                      (for prints \"CT1,... .\")"));
}
void loop() {
  pumpNextion();
  // làm việc khác nếu cần...
}
I want to send data n0n1n2=111 to arduino but serial is not read correctly, can someone help me, thank you very much!!!


