---
# System prepended metadata

title: Multi-Node CAN control based on FreeRTOS

---

# Multi-Node CAN control based on FreeRTOS
**Reference:[成大Wiki]([http:](https://wiki.csie.ncku.edu.tw/embedded/CAN)), [CAN Bus: Serial Communication - How It Works?](https://www.youtube.com/watch?v=JZSCzRT9TTo)**
## Intro
This note's purpose is to record the implementation and process of year training plan, this tiny project fouse on the CANbus communication protocol, then apply this technical skill into virtual vehicle environment. 
## CANbus
試想一個車載環境如下圖:
![image](https://hackmd.io/_uploads/BkuWbjEP1e.png)
我們需要結合許多節點裝置的資訊來控制其他節點裝置，那是否存在一種高擴充性、高可靠度但低成本的通訊方式串聯所有的裝置?

控制器區域網路(Controller Area Network, 簡稱 CAN 或 CANbus)是一種網路，其特點是允許網路上的多個微控制器或設備直接互相通訊，網路上不需要主機(Host)控制通訊，並且提供高安全等級及有效率的即時控制。更具備了偵錯和優先權判別的機制，網路訊息的傳輸變的更為可靠而有效率。訊息的ID並不是定義在節點，而是定義在訊息上，所以只要在軟體上修正就能夠輕易增加或移除節點，增加了在升級網路時的便利性。實作上又因為只需雙線溝通的特性，也降低線路複雜易造成錯誤的發生機會。
![image](https://hackmd.io/_uploads/SkG2r9NPkg.png)
#### Transmit principle
在車載環境中，我們會面臨各種電子干擾(ex.馬達震動、音響的磁場)，如果我們只用單線收/發訊號，就有可能因震盪造成資料錯誤。
![image](https://hackmd.io/_uploads/Hk1RYqNwJl.png)
![image](https://hackmd.io/_uploads/B1sCc5ED1e.png)

利用<font color="#ff0000">差分訊號</font>完美的解決這個問題，因此CANbus需要使用雙絞線進行收發。
![image](https://hackmd.io/_uploads/H1P_6cEvkg.png)
#### Data frame
主要有五種資料格式:
1. Standard CAN data frame
2. Extended CAN data frame
![image](https://hackmd.io/_uploads/Sy3m3kUwke.png)
    * SOF : Start Of Frame，開始時送出一個0 bit作為同步用途。
    * Arbitration Field : 仲裁欄，用來判別節點傳送的先後優先權，位元為0可以優先收發，長度有兩種11 bits(standard)和29 bits(extended)，
![image](https://hackmd.io/_uploads/HJefO1Lwke.png)
RTR則為判斷要傳送(0)還是接收(1)。
    * Control Field : 收發的資料長度，共4 bits組合，
![image](https://hackmd.io/_uploads/B1hhKkUDkl.png)
IDE設定標準格式(Standard identifier)為dominant(0)；延伸格式(Extended Identifier)為 recessive(1)。
r0保留位。
    * Data Field : 0-8 bytes的資料。
    * CRC Field : 偵錯碼。
    * ACK Field : 確認應答機制，傳送端送出一個1後當接收正確該接收設備會傳送 0。
    * EOF : 通訊結束欄位，每筆資料都是由7個bit的1當作結束的判斷。
3. Remote frame : 請求遠端節點傳送資料時，遠端通訊格式基本上就是資料長度為0的資料通訊格式，指示設定上略有不同。當A節點需要B節點送出資料時，可藉由送出一個遠端通訊格式來完成，將B節點的ID寫入仲裁欄位，在RTR填入recessive(1)。
4. Error frame : 當接收到的訊息有錯誤時，節點會發送錯誤通訊格式通知其他節點。
5. Overload frame : 假如設備需要更多時間處理時，可以使用超載通訊格式來延遲下一筆資料的時間，接再遠端通訊格式or資料通訊格式之後。
#### Identifier filtering
濾波器對於CAN是非常重要的一個機制，由於CAN在傳送資料的過程是類似廣播的方式，所以在節點數量眾多的時候，我們可以利用濾波器決定要與不要接收哪些訊息來減輕節點的負擔。<font color="#ff0000">須注意濾波器一定要設定開啟才能接收CAN各節點的訊息。</font>
```c
/**
  * @brief  CAN filter configuration structure definition
  */
typedef struct
{
  uint32_t FilterIdHigh;
//設定濾波器的高 16 位，用於存儲標準 ID（11 位，左移 5 位對齊）或擴展 ID 的高 16 位。
  uint32_t FilterIdLow;        
//設定濾波器的低 16 位，用於存儲擴展 ID 的低 16 位。通常是0x0000
  uint32_t FilterMaskIdHigh;    
//設置濾波器掩碼的高 16 位，用於篩選消息 ID 的高部分。
//掩碼位為 1 表示該位需要匹配，為 0 表示忽略該位。
  uint32_t FilterMaskIdLow;     
//設置濾波器掩碼的低 16 位，用於篩選擴展 ID 的低部分。通常是0x0000
  uint32_t FilterFIFOAssignment;  
//指定接收到的消息應存儲在哪個接收 FIFO。
  uint32_t FilterBank;           
//指定濾波器組的索引，不同的濾波器組可以配置不同的濾波條件。
  uint32_t FilterMode;           
//工作模式: CAN_FILTERMODE_IDMASK -> 通過 FilterId 和 MaskId 的篩選條件接收消息。
//         CAN_FILTERMODE_IDLIST -> 只接收與 FilterId 完全匹配的消息。
  uint32_t FilterScale;       
//設定濾波器的位寬。
  uint32_t FilterActivation;   
//指定是否啟用該濾波器。
  uint32_t SlaveStartFilterBank;  

} CAN_FilterTypeDef;
```
#### Bit timming
由於CAN僅透過兩條收發線傳送訊號，屬於一種非同步通訊協定，因此必須設定相同的波特率在每個節點。
![image](https://hackmd.io/_uploads/r1rFRxIDJg.png)

:::info
:open_book: 
同步 : 依靠時鐘訊號(CLK)同步資訊。
非同步 : 沒有時鐘訊號，必須藉由baudrate來達到位同步機制。
:::


