บทเรียน 4.4 — CAN bus 500 kbps: ส่ง heartbeat และอ่านเฟรม

CAN bus 500 kbps: ส่ง heartbeat และอ่านเฟรม

TESAIoT Dev Kit · PSoC Edge E84 · ภาษา C · ModusToolbox

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

เป้าหมาย

เมื่อจบบทเรียนนี้ คุณจะ

  1. ส่งเฟรม heartbeat 1 Hz ผ่าน CANFD0 แบบ Classic CAN 2.0A ที่ 500 kbps
  2. อ่านเฟรมที่เข้ามา แสดงเฟรมล่าสุด (ID และข้อมูล) และตัวนับเฟรมที่รับและส่ง
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ก่อนเริ่ม

  • ผ่านบทเรียนก่อนหน้ามาแล้ว: fw-stack.m01.l01
  • บอร์ด: TESAIoT Dev Kit
  • แพลตฟอร์ม: PSoC Edge E84 · ModusToolbox
  • เวลาโดยประมาณ: เนื้อหา 10 + ฝึกตาม 25 + แล็บ 30 + เช็กความเข้าใจ 5 = 70 นาที
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ดูของจริงก่อน

แบบฝึกของ Developer Hub ที่เขียนไว้สำหรับบอร์ดฐาน QWA309 โดยตรง — เปิดบน Developer Hub แล้ว flash เฟิร์มแวร์สำเร็จรูปดูก่อนว่าหน้าจอเป็นอย่างไร

  • QWA309 — CAN Bus Monitor — CANFD0 Classic CAN 2.0A @ 500 kbps (P16.2 RX / P16.3 TX, SN65HVD230) บน CM55 แบบ polled — TX heartbeat 1Hz + RX frame table บน LVGL
    README · โค้ด · Developer Hub
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — บอร์ดฐาน QWA309 มีอะไรให้ฝึก

CAN transceiver บนบอร์ดฐาน — ตั้ง CANFD0 เป็น Classic CAN 2.0A ล้วน (ไม่ใช้ฟีเจอร์ CAN FD) ที่ 500 kbps

ทั้งส่งและรับเฟรมในโปรแกรมเดียว บนแกน CM55

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — bit timing ที่รวมกันได้ 500 kbps

clock 100 MHz · prescaler 10 · TS1 15 · TS2 4 (รีจิสเตอร์เก็บ n−1)

1 บิต = 1+15+4 = 20 quanta · 100/10=10 MHz ÷ 20 = 500 kbps · sample point = 16/20 = 80%

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — ตั้งค่าทั้งหมดด้วยโค้ด PDL ล้วน

can_pins_init() HSIOM P16.2/P16.3 → can_clock_init() จ่าย peripheral clock → Cy_CANFD_EnableMRAM() → Cy_CANFD_Init(&g_cfg)

ไม่แตะ Device Configurator เลย

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — โหมด polled ล้วน ไม่มี ISR

txCallback/rxCallback/errorCallback = NULL ไม่ลงทะเบียน NVIC

ส่ง-รับทำงานใน can_timer_cb() บน lv_timer ทุก 250 ms — รันในงาน LVGL เดียวกับที่วาดจอ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — heartbeat 1 ครั้ง/วินาทีด้วย one-shot TX (DAR)

ส่งทุก CAN_TX_EVERY_TICKS=4 รอบ (4×250ms=1s) ตั้งบิต DAR ปิด auto-retransmit

g_tx_count เพิ่มเมื่อ ส่งสำเร็จเข้าคิว เท่านั้น ไม่ได้แปลว่ามีใครรับจริง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — รับเฟรมทีละเฟรมต่อรอบโพล

can_poll_rx() ดึงจาก FIFO (4 ช่อง) แค่ 1 เฟรม/ครั้ง ที่ 250 ms/ครั้ง → รับได้สูงสุด ~4 เฟรม/วินาที

peer ส่งเร็วกว่านี้ FIFO เต็ม เฟรมส่วนเกินหายไปเงียบ ๆ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — arbitration: dominant ชนะ ไม่ใช่ "เลขน้อยกว่า"

บิต 0 (dominant) ชนะบิต 1 (recessive) เสมอเมื่อชนกัน — ID ที่บิตสูงเป็น 0 จึงชนะ ไม่ใช่การเทียบตัวเลข

ต้องมี terminator 120 Ω ที่ปลายสายทั้งสองด้าน (P9) ลดการสะท้อนสัญญาณ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แนวคิด — ทักษะที่ฝึกในบทเรียนนี้

บทเรียนนี้พัฒนาทักษะต่อไปนี้ (ตามระดับ 1–5 ของหลักสูตร)

  • proto.can (ระดับ 2)
  • gui.hmi (ระดับ 2)
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ตัวอย่างสมบูรณ์ — ตั้งบิต DAR (one-shot TX)

can_monitor_ui.c

if (CY_CANFD_SUCCESS != Cy_CANFD_Init(CANBUS_HW, CANBUS_CHANNEL,
                                       &g_cfg, &g_ctx)) {
    return false;
}
Cy_CANFD_ConfigChangesEnable(CANBUS_HW, CANBUS_CHANNEL);
/* One-shot TX: disable automatic retransmission so a frame
 * is not held pending an ACK when no peer node is on the bus. */
CANBUS_HW->CH[CANBUS_CHANNEL].M_TTCAN.CCCR |=
    CANFD_CH_M_TTCAN_CCCR_DAR_Msk;
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ตัวอย่างสมบูรณ์ — โพล RX FIFO ครั้งเดียวต่อรอบ

can_monitor_ui.c

static void can_poll_rx(void)
{
    uint32_t irq = Cy_CANFD_GetInterruptStatus(CANBUS_HW, CANBUS_CHANNEL);
    if (0U != (irq & CY_CANFD_RX_FIFO_0_NEW_MESSAGE)) {
        if (CY_CANFD_SUCCESS ==
            Cy_CANFD_GetFIFOTop(CANBUS_HW, CANBUS_CHANNEL, 0U, &g_rx_buf)) {
            g_last_rx_id  = g_r0.id;
            g_last_rx_dlc = g_r1.dlc;
        }
        Cy_CANFD_AckRxFifo(CANBUS_HW, CANBUS_CHANNEL, 0U);
    }
}
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

จุดที่มักพลาด

  • ตัวนับ TX เพิ่มขึ้น ≠ มีคนรับเฟรม — DAR ปิดการรอ ACK ไว้ ต้องมี node อื่นยืนยัน
  • ต่อบัสจริงไม่ใส่ terminator 120 Ω — สัญญาณสะท้อน อ่านบิตผิด แต่ใส่ทุก node ก็ผิดเช่นกัน
  • คาดว่าจะรับได้ทุกเฟรม — โพลได้แค่ 1 เฟรม/250 ms เฟรมส่วนเกินหายไปเงียบ ๆ
  • คิดว่า ID น้อยกว่าชนะเพราะเป็นตัวเลข — จริงคือกลไกไฟฟ้า (dominant ชนะ recessive)
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ตัวอย่างสมบูรณ์ — build และ flash

แบบฝึกชุด QWA309 ของ Developer Hub (อ้างอิงที่ commit e5c7722) รันบน TESAIoT Dev Kit เท่านั้น เพราะใช้อุปกรณ์บนบอร์ดฐาน

# ในโฟลเดอร์ master template (ดูบทเรียน 1.1)
# 1) ลบไฟล์ของ episode เก่าใน proj_cm55/apps/
# 2) คัดลอกไฟล์ทั้งหมดของ episode นี้ลงใน proj_cm55/apps/
make build
make program     # flash ผ่าน KitProg3
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ฝึกเติม / แล็บ

  1. ทาย ก่อนแก้: เลือกค่าหนึ่งค่าที่ README ของตัวอย่างอธิบายไว้ในส่วน How แล้วเขียนว่าจะเห็นอะไรเปลี่ยนบนจอหรือใน log
  2. แก้และรัน build + flash แล้วเทียบกับที่ทายไว้ ถ้าไม่ตรง ให้หาว่าเข้าใจส่วนไหนผิด
  3. ทำเพิ่ม ต่อยอดหนึ่งอย่างที่ตัวอย่างยังไม่มี แล้วเก็บภาพหรือวิดีโอไว้ใน portfolio
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

เช็กความเข้าใจ

  • ทำไม CAN bus ต้องมี termination ที่ปลายสาย
  • ID ของเฟรม CAN บอกอะไรนอกจากชื่อข้อความ

คำตอบอยู่ใน README ของตัวอย่างและในโค้ด ถ้าตอบข้อใดไม่ได้ ให้กลับไปอ่านส่วน Why / What / How อีกครั้ง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

ไปต่อ

  • ทบทวนเป้าหมายทั้ง 2 ข้อของบทเรียนนี้ก่อนไปต่อ
  • ถ้าตอบคำถามหน้าที่แล้วไม่ได้ครบ กลับไปอ่าน README ของตัวอย่างส่วน Why / What / How อีกครั้ง
  • พร้อมแล้วไปเปิดบทเรียนถัดไปในโมดูลเดียวกัน
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

แหล่งอ้างอิง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

เครดิต

"TESAIoT Firmware Stack: เฟิร์มแวร์ภาษา C บน TESAIoT Dev Kit" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0

ตัวอย่างโค้ดเป็นผลงานของ TESAIoT Firmware Stack โดยสมาคมสมองกลฝังตัวไทย (TESA) ใน tesaiot/developer-hub รายละเอียดการให้เครดิตอยู่ที่ ATTRIBUTION.md

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0