建立以下文件夾:
inc文件夾:放LM3S8962硬件相關以及驅動部分的頭文件,adc.h、hw_adc.h等等;
Lib文件夾:放集成庫文件driverlib.lib,這個需要比較新的,因為遇到老的庫文件缺少CANbitset()函數;
Startup文件夾:放啟動代碼,Keil軟件自身提供的,只需要加入定時器中斷(CANopen需要一個16位定時器)和CAN接收中斷處理函數;
Target文件夾:目標板初始化代碼,其實就是設置系統時鍾吧!其實設置的50M;
CANopen_source文件夾:包括CANopen源文件,下載的源碼中有13個,不過本次移植dcf.c、lss.c、symbols.c文件沒有用到,其中不包含對象字典文件ObjDict.c,該文件我們選取的是examples\AVR\Slave中的ObjDict.c,是從節點的對象字典;
CANopen_include文件夾:包括CANopen頭文件,即下載的文件夾的\include目錄下的公共文件19個,然后我們把ObjDict.h加進來了,那一共20個,但是有2個應該不會用到(lss.h、dcf.h),因為未用對應的C文件;
user文件夾:存放main.c、includes.h(包括inc中的頭文件以及其他文件如CANopen相關的)、以及\include\AT91目錄下的4個頭文件,分別為applicfg.h、canfestival、config.h、timerscfg.h
需要注意的地方:
CANopen中的timer.h和can.h與庫頭文件中的文件重名了,需要修改CANopen中的文件名,而且CANopen源文件中引用該頭文件的地方也需要修改過來,我們將其改名為CANopen_timer.h、CANopen_can.h。Keil軟件提供了全局查找的功能,可以方便查找。
Keil里全局查找Message時,在.h文件中沒有找到,其實在CANopen_can.h中有Message的定義,估計是h文件沒有包含進入工程吧!我們只是option for target中的C/C++的包含目錄中添加了頭文件所在的路徑,以后可以將h文件加入工程!!!
建立新的工程,將上述文件加入工程,然后編寫簡單的main.c函數,開始編譯改錯
編譯錯誤:
1)SDO中發現SDO_BLOCK_SIZE常量未定義,在SDO.c中增加定義#defineSDO_BLOCK_SIZE 10
2)CO_Data結構體中用到了未定義的ObjDict_obj100C,故在對象字典中增加定義
3)Link錯誤:比如未實現voidsetTimer(TIMEVALvalue)、TIMEVALgetElapsedTime(void)等等。實現上述函數是移植的關鍵
......
修改直至編譯通過,然后寫簡單的測試代碼,測試心跳報文、TPDO、RPDO、SDO功能,當然是從最簡單的心跳報文開始,測試時發現了犯了一個錯誤,搞錯UNS8canSend(CAN_PORT notused, Message *m)函數類型,之前采用的UNS8canSend(Message *m) ,解決這個問題后所有的功能就正常了。這個是通過跟蹤調試發現的,具體跟蹤如下:
setState(&ObjDict_Data, Initialisation); 之后會自動跳到Pre_operational狀態,該狀態支持{0, 1, 1, 1, 1, 0, 1};分別對應csLSS、csSDO、csSYNC、csLifeGuard、csEmergency、csPDO、csBoot_Up,由此可知僅不支持csLSS和csPDO功能。
switchCommunicationState()中會執行StartOrStop(csLifeGuard,lifeGuardInit(d),lifeGuardStop(d))
這就會執行lifeGuardInit(d), 就會執行heartbeatInit(d);定時時間到就會執行ProducerHeartbeatAlarm(),該函數就會調用底層CAN發送函數canSend(d->canHandle,&msg );發送心跳報文,幀ID為0x701
SDO測試結果截圖,讀取對象字典對象索引0x1017的第0個數據(標號是從0開始的)
USB-CAN卡發送幀ID 0x601 數據40 17 10 00 00 00 00 00//
從節點返回: 幀ID 0x581 數據4b 17 10 00 10 27 00 00
USB-CAN卡發送幀ID 0x601 數據23 00 18 01 01 02 00 00//改寫索引0x1800子索引0x01即TPDO1對應的幀ID為0x00000201從節點返回: 幀ID 0x581 數據40 00 18 01 00 00 00 00//讀取索引0x1800子索引0x01即TPDO1對應的幀ID
USB-CAN卡發送SYNC,從節點收到之后C觸發發送TPDO,我們設置的TPDO是同步方式,而且受到一個SYNC就發送TPDO


從以上結果可以知道移植的CANopen從節點功能正常。
調試時還發現一個問題:
TIMER_HANDLE SetAlarm()函數中有一條語句有問題,需要加上強制類型轉換:
if (row_number == (TIMER_HANDLE)last_timer_raw + 1) last_timer_raw++;
也即下面的問題:
U16 i = 0;
U16 j = -1;
i != (j + 1),其實j + 1為65536
故需要加強制類型轉換
i == (U16)(j + 1) 成立
