Giao tiếp CAN trên các board STM32F103C8T6

Trong bài viết này sẽ nói về một trong những mạng giao tiếp phổ biến nhất của chuẩn OBD-II, đó là chuẩn CAN (Controller Area Network). Bên cạnh tổng quan về CAN, bài viết này sẽ hướng dẫn cách lập trình CAN Bus trên STM32F103 trên phần mềm CubeMX và KeilC 5, đồng thời đưa ra một vài ví dụ demo để mô tả cách hoạt động của CAN.

CAN ra đời như thế nào?

CAN được phát triển vào năm 1983 bởi công ty Robert Bosch GmbH. Trước thời điểm đó các loại xe oto trên thế giới còn tích hợp ít cảm biến và module nên chúng được liên kết bằng đường dây điện thông thường và kết nối theo dạng P2P (point to point).

Tuy nhiên càng về sau các loại xe oto càng được nâng cấp, tích hợp thêm nhiều module yêu cầu trao đổi thông tin thời gian thực, vì vậy kiểu kết nối cũ trở nên không hợp lý vì phải tốn thêm nhiều dây điện khiến hệ thống trở nên phức tạp… Vì vậy CAN được ra đời để tối ưu hiệu suất mạng lưới dây dẫn đó.

[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]

Nguyên lí hoạt động của CAN

CAN có nhiều loại nhưng có hai loại phổ biến nhất là High Speed CAN và Low Speed/Fault Tolerant CAN, tuy nhiên trong công nghiệp oto thì High Speed CAN được sử dụng phổ biến hơn.
Sơ đồ kết nối các module trong High Speed CAN:

Mỗi module được kết nối với nhau theo từng dây CAN-Hi và CAN-Low. Ở hai điểm đầu và điểm cuối của đường truyền dẫn sử dụng hai điện trở 120 Ohm mỗi đầu. Tốc độ kết nối tối đa của high speed CAN lên đến 1Mpbs.
Sơ đồ cấu trúc liên kiết mạng CAN:

Mỗi CAN node là một vi điều khiển (microcontroller – MCU) kết nối với một bộ điều khiển CAN (CAN – Controller). Bộ điều khiển CAN sẽ được kết nối với bộ chuyển đổi (hay bộ truyền-nhận) CAN – Transceiver thông qua 2 đường CAN Tx và CAN Rx. Chức năng của bộ chuyển đổi này là để chuyển đổi từ tín hiệu số trên đường TX thành tín hiệu tương tự trên bus CAN và chuyển đổi từ tín hiệu tương tự trên bus CAN (CAN_H và CAN_L) thành tín hiệu số trên RX.

Tạo project sử dụng tính năng CAN trên STM32F103C8T6

Bước 1: Kết nối phần cứng
Trong project này sử dụng 3 module STM32F103C8T6, 3 IC MCP2551 (CAN Transceiver), 3 led đơn và 3 nút nhấn. Dưới đây là sơ đồ kết nối board STM32F103C8T6 với IC CAN Transceiver. 

3 led các bạn nối với 3 chân PA3 của các board STM32, còn nút nhấn nối với chân PA0.

Bước 2: Thiết lập cấu hình trên Cube MX

Chọn PA3, PC13 làm chức năng GPIO Output, chân PA0 làm chức năng GPIO Input
Chuyển qua tab Configuration, kích chọn CAN:

Bước 3: Đặt tên cho Project và tạo code
Bước 4: Viết chương trình trên phần mềm Keil C v5

Sau khi tạo code từ CubeMX, ta tìm đến mục này trong file main.c của Keil C:

Kích chuột phải và chọn Go To Definition of ‘CAN_HandleTypeDef’, bạn sẽ thấy các kiểu dữ liệu đã được khai báo sẵn để hỗ trợ cho giao tiếp CAN. Trong đó có 2 structure nên lưu ý là CanTxMsgTypeDef (transmit structure) và CanRxMsgTypeDef (reception structure).

Bài viết này sẽ đưa ra 2 ví dụ:

Ví dụ thứ 1, các node CAN sẽ giao tiếp với nhau, khi một node gửi tín hiệu đi thì 2 node còn lại sẽ response lại.

– Ví dụ thứ 2, node CAN chỉ phản hồi tín hiệu của một node khác cụ thể, nếu nhận của node khác thì sẽ không phản hồi.

Ở mục /* USER CODE BEGIN PV */ khai báo các biến sau:

Đối với ví dụ 1, ở /* USER CODE BEGIN PFP */ ta gọi hàm callback như sau:

/* USER CODE BEGIN 2 */

Lưu ý: Mỗi board STM32F103C8T6, bạn nên thay đổi id khác nhau rồi nạp chương trình.

Trong hàm while(1):

Video demo ví dụ 1:

Ở ví dụ 2, các code đều giữ nguyên giống ví dụ 1, tuy nhiên hàm callback thay đổi như sau:

Chỉ nạp lại code mới vào 1 board STM32, sau đó chạy chương trình:

Các bạn có thể thử gửi các chuỗi dữ liệu giữa các STM32 với nhau thông qua giao tiếp CAN.

Xem thêm: Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32 tại đây