一、CAN子產品介紹
這個實驗我們來研究XEP100單片機内部的CAN子產品。
XEP100單片機的CAN的基本特性如下:
• 實施CAN協定—2.0A/B版
— 标準和擴充資料幀
— 0-8位元組資料長度
— 高達1Mbps的可程式設計比特率
— 支援遠端幀
• 5個具有FIFO存儲機制的接收緩沖器
• 3個具有使用“本地優先”概念的内部優先順序的發送緩沖器
• 靈活可掩碼辨別符濾波器支援2個全尺寸(32位)擴充辨別符濾波器或4個16位濾波器或8個8位濾波器
• 內建低通濾波器的可程式設計喚醒功能
• 可程式設計環回模式支援自測操作
• 可程式設計監聽模式用于CAN總線監控
• 可程式設計總線脫離恢複功能
• 獨立的信号和中斷功能适用于所有CAN接收器和發射器錯誤狀态(警報、錯誤嚴重狀态、總線脫離)
• 可程式設計CAN時鐘源,采用總線時鐘或振蕩器時鐘
• 内部計時器提供給接收和發送的封包的時間标簽
• 三種低功耗模式:睡眠、關機和CAN使能
• 配置寄存器的全局初始化
CAN子產品的結構圖如下:
圖中RXCAN是CAN接收器輸入管腳。TXCAN是CAN發送器輸出管腳。
下圖顯示了一個具有CAN的典型CAN系統。每個CAN節點通過收發器實體連接配接到CAN總線線路,收發器能夠驅動CAN總線所需的大電流,并具有對故障CAN或故障節點的電流保護。
CAN的接收器和發送器的結構如下圖所示。
CAN收到的封包儲存在5級輸入FIFO中。5個封包緩沖器被交替映射到單個存儲器區域。CAN有三重發送緩沖器機制,允許提前建立多條封包,進而優化了實時性能。
CAN的封包緩沖器結構見下表
Offset Address | Register | Access |
0x00X0 | Identifier Register 0 | |
0x00X1 | Identifier Register 1 | |
0x00X2 | Identifier Register 2 | |
0x00X3 | Identifier Register 3 | |
0x00X4 | Data Segment Register 0 | |
0x00X5 | Data Segment Register 1 | |
0x00X6 | Data Segment Register 2 | |
0x00X7 | Data Segment Register 3 | |
0x00X8 | Data Segment Register 4 | |
0x00X9 | Data Segment Register 5 | |
0x00XA | Data Segment Register 6 | |
0x00XB | Data Segment Register 7 | |
0x00XC | Data Length Register | |
0x00XD | Transmit Buffer Priority Register | |
0x00XE | Time Stamp Register (High Byte) | |
0x00XF | Time Stamp Register (Low Byte) |
有關CAN的更加詳細的資訊請參見相關的CAN協定和XEP100單片機的技術資料。
本實驗的CAN接口晶片采用的是TJA1050晶片,電路的原理圖如下圖所示。圖中L81和L82是CAN總線專用的濾波電感。J81和J82是跳線插針,用于連接配接120歐姆的電阻。如果CAN總線上挂接多個節點,隻能保留兩個120歐姆的電阻。這時需要把多餘的電阻切斷。就要拔下相應的跳線帽。
本實驗采用CAN0發送資料,CAN1接收資料,CAN資料的格式采用标準幀格式。在開發闆上通過自發自收實驗來模拟真實的CAN通信過程。
二、例程測試
本實驗的例程可以從本文的資源中下載下傳。打開例程的代碼,可以發現程式有些負責,程式中将CAN子產品的驅動以及LCD的驅動封裝到獨立的檔案當中,在主檔案中進行調用。由于代碼比較多,我們隻對CAN的驅動函數進行功能性的介紹,具體細節可以對照着晶片手冊進行研究。
1、CAN初始化
CAN子產品的初始化函數如下所示。
void INIT_CANx(void);
這個函數的作用是對CANx子產品進行初始化,将波特率設定為250kbit/s,禁止CAN濾波功能。
2、CAN發送函數
CAN子產品的發送函數如下所示
Bool MSCANxSendMsg(struct can_msg msg);
這個函數的作用是通過CANx子產品發送資料,struct can_msg msg為需要發送是資料的結構體,函數傳回值為是否成功,發送成功傳回true。struct can_msg msg結構體的定義如下。
struct can_msg //發送封包的結構體
{
unsigned int id;
Bool RTR;
unsigned char data[8];
unsigned char len;
unsigned char prty;
};
結構體中包含了資料幀的ID,RTR标志位,8個位元組的資料,資料長度和優先級。
3、CAN接收函數
CAN子產品的接收函數如下所示
Bool MSCANxGetMsg(struct can_msg *msg);
函數中struct can_msg *msg為指向接收到的資料結構體的指針,函數傳回接收是否成功,成功傳回true。
這個程式的主函數如下所示
void main(void) {
DisableInterrupts;
INIT_PLL();
initialize_ect();
INIT_PORT();
INIT_CAN0();
INIT_CAN1();
LEDCPU_dir=1;
LEDCPU=0;
EnableInterrupts;
//填寫封包内容
msg_send.id = ID;
for(k=0;k<data_len_TX;k++)
{
msg_send.data[k] = senddata[k];
}
msg_send.len = data_len_TX;
msg_send.RTR = FALSE;
msg_send.prty = 0;
for(;;)
{
delay1ms(1000);
if(!MSCAN0SendMsg(msg_send)) //發送過程出現錯誤
{
for(;;);
}
if(datain==1)
{
lcd_clear();
lcd_string(0,0,xianshi[0]);
lcd_string(1,0,xianshi[1]);
play_data();
datain=0;
}
}
}
主函數的作用是通過CAN0發送資料,首先将需要發送的資料的ID和data指派到發送結構體中,然後在主循環中每個1秒發送一次資料。并且在接收到資料時,在lcd上顯示接收到的資料。
CAN1負責接收資料,接收采用中斷的方式,中斷函數如下所示。
void interrupt CAN_receive(void)
{
if(MSCAN1GetMsg(&msg_get))
{
// 接收新資訊
if(msg_get.id == ID && (!msg_get.RTR))
{
LEDCPU = ~LEDCPU;
datain=1;
}
}
else
{
for(;;);
}
}
在中斷函數中,主要是通過CAN1的接收函數來接收資料,接收成功後設定标志位datain。
将程式下載下傳到單片機中,并将單片機的CAN0和CAN1接口連接配接在一起,運作程式,可以看到液晶上顯示接收到的資料。