近期完成了CAN模塊數(shù)據(jù)收發(fā)的調(diào)試,用到的芯片有CAN控制器:MCP2518FD和CAN收發(fā)器:ADM3057E。通過FPGA-XC7A35T開發(fā)板的SPI接口與分別與兩個(gè)MCP2518FD相連,分別對(duì)其進(jìn)行寄存器的讀寫以及RAM的讀寫,控制其中一個(gè)發(fā)送數(shù)據(jù),另一個(gè)接收數(shù)據(jù),從而實(shí)現(xiàn)了CAN協(xié)議數(shù)據(jù)發(fā)送與接收功能的調(diào)試。
一、SPI通信:
首先要實(shí)現(xiàn)FPGA與MPC2518FD的SPI通信,從而實(shí)現(xiàn)對(duì)其寄存器的讀寫配置。新建vivado工程,Creat block design,添加軟核以及兩個(gè)自己的SPI核,進(jìn)行連線等后續(xù)工作。最終的block design如圖所示

為兩個(gè)SPI核分配地址。Generate output products,然后Create HDL wapper,生成HDL頂層文件,將PS端當(dāng)做一個(gè)IP核來使用。新建V文件,例化Wrapper核并添加ILA進(jìn)行兩組SPI 8個(gè)信號(hào)的監(jiān)控。創(chuàng)建XDC文件,將物理引腳進(jìn)行管腳約束和時(shí)鐘約束。
編譯綜合后生成bit文件,Export Hardware,Launch SDK,啟動(dòng) SDK 開發(fā)環(huán)境。在SDK里進(jìn)行C語(yǔ)言的編程,實(shí)現(xiàn)通過SPI對(duì)MCP2518FD寄存器的讀和寫。將自己的SPI核對(duì)應(yīng)的C語(yǔ)言讀寫函數(shù)直接拿來用,發(fā)現(xiàn)無法進(jìn)行讀寫,仔細(xì)對(duì)比芯片手冊(cè)的SPI讀寫時(shí)序和自己的SPI讀寫時(shí)序,發(fā)現(xiàn)并解決了問題:
手冊(cè)SPI時(shí)序:

錯(cuò)誤(寫不進(jìn)去):

正確(能寫進(jìn)去):

錯(cuò)誤原因:數(shù)據(jù)位最后一位末與cs信號(hào)上升沿重合,正確的時(shí)序?yàn)閏s信號(hào)再過至少半個(gè)周期再拉高。
解決方法:ps端發(fā)數(shù)的時(shí)候要多發(fā)一位,即數(shù)據(jù)位要發(fā)9位(2進(jìn)制表示時(shí))或者12位(16進(jìn)制表示時(shí)),即可將前8位正確寫入寄存器中。(該方法僅針對(duì)自己的SPI IP核)
二、芯片初始化:
實(shí)現(xiàn)了FPGA與MPC2518FD的SPI通信后,我們可以對(duì)其寄存器進(jìn)行讀寫配置了。接下來要做的是閱讀MPC2518FD的芯片手冊(cè),找到需要配置的寄存器,將其功能配置為一個(gè)發(fā)送數(shù)據(jù),一個(gè)接收數(shù)據(jù)。芯片手冊(cè)上有每個(gè)寄存器具體到每一個(gè)位的功能,然而只看這些對(duì)于直接寫整個(gè)程序還是有一定難度的。于是我去微芯的官網(wǎng)www.microchip.com上下載了該芯片的開發(fā)手冊(cè),以及底層驅(qū)動(dòng)的C語(yǔ)言庫(kù)。
開發(fā)手冊(cè)上介紹了芯片初始化、發(fā)送數(shù)據(jù)、接收數(shù)據(jù)的步驟。如圖是初始化的例子

雖然手冊(cè)上給了初始化步驟和例程代碼,但是沒有具體告訴你需要配哪個(gè)寄存器以及每個(gè)位怎么配置,所以我們要看官網(wǎng)上下載的底層驅(qū)動(dòng)的C語(yǔ)言庫(kù),看懂他例程代碼底層具體配了哪個(gè)寄存器,每個(gè)位具體怎么配的,然后轉(zhuǎn)換成自己SPI讀寫的代碼。我們按手冊(cè)的步驟配置每個(gè)需要配置的寄存器,將兩個(gè)芯片初始化,并且將兩個(gè)寄存器C1FIFOCON1的TXEN位分別置1和0,其功能配置為一個(gè)發(fā)送數(shù)據(jù),一個(gè)接收數(shù)據(jù)。
三、數(shù)據(jù)的發(fā)送:
發(fā)送數(shù)據(jù)有兩種方式:FIFO發(fā)送和隊(duì)列發(fā)送,這里我們采用FIFO發(fā)送。不管哪種發(fā)送方式,都要將待發(fā)送的數(shù)據(jù)存入RAM里。RAM起始地址為0x400,待發(fā)送數(shù)據(jù)的地址為:

當(dāng)然我們也可以自己計(jì)算數(shù)據(jù)的起始地址。如圖所示,RAM里存放數(shù)據(jù)的位置是根據(jù)TEF,TX Queue,F(xiàn)IFOn的順序排列的,TEF的起始地址永遠(yuǎn)為0x400,TX Queue地址為0x400地址加上TEF中數(shù)據(jù)的字節(jié)數(shù),F(xiàn)IFO1的起始地址為0x400地址加上TEF和TX Queue中數(shù)據(jù)的字節(jié)數(shù)。我們這里只采用FIFO1發(fā)送數(shù)據(jù),所以我們配置C1CON寄存器,關(guān)閉TEF和TX Queue使能位,此時(shí)它們不再占用RAM的空間。所以我們用FIFO1發(fā)送數(shù)據(jù)的起始地址就是0x400。

找到了RAM的起始地址后,我們要將數(shù)據(jù)寫進(jìn)RAM里,這里和寫寄存器不一樣,必須要一次性寫4或4的倍數(shù)個(gè)字節(jié),才能將數(shù)據(jù)寫入RAM里。我們對(duì)SPI底層讀寫代碼進(jìn)行了修改,將第二行改為了(value>>32)&0xffffffff000fffff,成功的一次性寫和讀了4個(gè)字節(jié),將數(shù)據(jù)寫進(jìn)了RAM并能成功讀出來。注意寫的時(shí)候也是要在4個(gè)字節(jié)后多寫一位才能寫進(jìn)去。

接下來查看需要發(fā)送的數(shù)據(jù)的CAN幀格式,如圖所示:

這里我們發(fā)送標(biāo)準(zhǔn)幀,將SID配置為0x300。FDF位置1將幀類型選擇為CAN FD,置0則選擇為CAN 2.0 。DLC位配置為8,即令數(shù)據(jù)字節(jié)一共有8個(gè)。數(shù)據(jù)字節(jié)我們發(fā)送01-08的遞增數(shù)。這樣一個(gè)完整的標(biāo)準(zhǔn)幀就拼好了,我們將其寫到RAM里。

接來下將發(fā)送使能位:寄存器C1FIFOCON1的TXREQ位置1,完成數(shù)據(jù)發(fā)送。

四、數(shù)據(jù)的接收:
數(shù)據(jù)接收采用另一個(gè)芯片的FIFO1,也是先配置C1CON寄存器,關(guān)閉TEF和TX Queue使能位,此時(shí)它們不再占用RAM的空間。所以我們用FIFO1接收數(shù)據(jù)的起始地址也是0x400。
數(shù)據(jù)接收時(shí),還需要配置一個(gè)過濾器,只接收指定ID的CAN報(bào)文。根據(jù)手冊(cè)例程,配置相應(yīng)寄存器,使能過濾器,只接收SID為0x300-0x30F的CAN報(bào)文。

接收時(shí)的CAN幀格式如圖所示

R2只有在CiFIFOCONm.RXTSEN置1時(shí)存在,這里我們置0,即R2不存在。所以我們發(fā)送的數(shù)據(jù)幀格式也符合接收的數(shù)據(jù)幀格式。
我們從RAM里4個(gè)字節(jié)一組讀發(fā)送的數(shù)據(jù),并存在rxd這個(gè)數(shù)組里。

五、調(diào)試與結(jié)果
我們將兩個(gè)ADM3057E芯片的CAN_H腳互連,CAN_L腳互連,CAN_GND腳互連,F(xiàn)PGA通過8個(gè)腳分別連兩個(gè)MCP2518芯片的SPI接口,并且共地。兩個(gè)MCP2518芯片的MCP25_*INT腳互連。給FPGA下載verilog程序,SDK里加載C語(yǔ)言程序。C語(yǔ)言要注意先初始化兩個(gè)芯片,再使能數(shù)據(jù)發(fā)送,最后進(jìn)行數(shù)據(jù)讀取。

最終我們成功的在rxd數(shù)組里讀取到了發(fā)送的數(shù)據(jù)。

發(fā)送的數(shù)據(jù)

接收的數(shù)據(jù)
如圖所示,可見收到的數(shù)據(jù)和發(fā)送的數(shù)據(jù)是一樣的,成功實(shí)現(xiàn)了CAN協(xié)議數(shù)據(jù)一發(fā)一收的功能。
0755-83660119