《四》canfestival系列教程之pdo發(fā)送流程代碼分析
在canfestival中發(fā)送pdo需要:
用配套上位機(jī)軟件生成字典.
配置好定時(shí)器.
切換canopen總線狀態(tài).(canfestival會(huì)根據(jù)配置,在中斷里自動(dòng)發(fā)送,不需要人干預(yù))
下文中的圖片看不清,可全屏看圖,或保存圖片下來(lái).

canfestival的所有參數(shù)都記錄在了字典里面,包括pdo的映射關(guān)系.
例如:
pdo1發(fā)送的數(shù)據(jù)是速度.
pdo2發(fā)送的數(shù)據(jù)是位置.
......
這些關(guān)系都記錄在了字典里面.

canfestival中發(fā)送pdo程序會(huì)自動(dòng)幫你創(chuàng)建一個(gè)軟件定時(shí)器.
用于該事件的管理.
如果發(fā)一次性的pdo,那么軟件定時(shí)器只執(zhí)行一次,然后被銷(xiāo)毀.
如果發(fā)送循環(huán)的pdo,軟件定時(shí)器會(huì)被設(shè)置成周期觸發(fā)的.
除了pdo,sdo,同步幀等事件也都有各自的軟件定時(shí)器.

配置好字典.配置好時(shí)鐘.
在主函數(shù)中通過(guò)canfestival的接口函數(shù),切換can總線的狀態(tài)為操作狀態(tài),
程序就會(huì)根據(jù)配制好的硬件定時(shí)器,啟動(dòng)軟件定時(shí)器,然后軟件定時(shí)器溢出后.
調(diào)用回調(diào)函數(shù),發(fā)送pdo.
只要配置好參數(shù),啟動(dòng)總線.剩余的事情是不用管的.主函數(shù)只留空循環(huán)就行.
這樣看起來(lái)canfestival還是比較好用的.

了解了上面框架,
下面我們按照原碼去分析一下pdo是怎么發(fā)送出去的.
1.先從字典入手
canfestival的字典是通過(guò)上位機(jī)進(jìn)行生成的.
賦值代碼在字典.c文件的最后一行.

每個(gè)人生成的文件名不一樣.
我這的文件名叫做Master.所以傳入的參數(shù)就是Master.這個(gè)CANOPEN_NODE_DATA_INITIALIZER并不是函數(shù),而是一個(gè)宏定義.通過(guò)這個(gè)宏定義,會(huì)把字典.c里面的內(nèi)容傳給一個(gè)CO_Data類(lèi)型的結(jié)構(gòu)體變量.我這里面?zhèn)魅氲氖荕aster_Data這個(gè)變量.之后在主函數(shù)中調(diào)用Master_Data,就可以獲得字典中的所有參數(shù).
賦值的流程
CANOPEN_NODE_DATA_INITIALIZER是宏定義,里面用到了##連接符.連接符的作用就是吧##前后的兩個(gè)東西合到一起,我們舉個(gè)例子.
因?yàn)槲疑傻淖值涿纸凶?span id="s0sssss00s" class="color-pink-03">Master.c,所以在字典文件中會(huì)有一個(gè)變量,Master_objdict.這里生成字典名字不同,變量名也會(huì)隨之改變.

Master_objdict[]是字典里的變量,最終會(huì)通過(guò)
CO_Data Master_Data = CANOPEN_NODE_DATA_INITIALIZER(Master);
賦值給Master_Data_objdict.
因?yàn)?



2.分析字典參數(shù)
例子:
因?yàn)樗饕?x1800,所以代表這個(gè)是pdo1? (ds301中有規(guī)定)
因?yàn)?1h子索引是0x201,說(shuō)明發(fā)送pdo的id號(hào)是201.
因?yàn)?2h子索引是0xff? ? ,說(shuō)明發(fā)送pdo的方式是定時(shí)器觸發(fā).
因?yàn)?5h子索引是0x05? ,說(shuō)明發(fā)送pdo的周期是5ms(注意這里是16進(jìn)制的).

上面通過(guò)配置字典中的通訊參數(shù),配置了pdo的發(fā)送方式.
下面通過(guò)配置字典中的映射參數(shù),配置pdo的傳輸數(shù)據(jù)類(lèi)型和意義.
映射參數(shù)索引為0x1A00 (因?yàn)槭怯玫膒do1,所以這里是規(guī)定好的,只能用0x1A00,ds301協(xié)議)
這樣,因?yàn)榕渲脼?x60ff0020,所以傳輸?shù)臄?shù)據(jù)是"速度值",類(lèi)型是32位無(wú)符號(hào).
(ds402中規(guī)定 : 索引0x60ff 子索引 00中的參數(shù)代表"速度值", 20代表32位無(wú)符號(hào)類(lèi)型)


3.定時(shí)器配置
通過(guò)上面配置,pdo的參數(shù)已經(jīng)完成了.
下面配置時(shí)鐘.
需要配置一個(gè)定時(shí)器,然后定時(shí)器需要設(shè)置成中斷模式.
在中斷函數(shù)中調(diào)用canfestival的接口函數(shù)TimeDispatch();
需要配置timerscfg.h文件中三個(gè)變量.

還需要編寫(xiě)相應(yīng)的兩個(gè)函數(shù),需要根據(jù)開(kāi)發(fā)環(huán)境進(jìn)行編寫(xiě)
TIMEVAL getElapsedTime(void)和void setTimer(TIMEVAL value)


4.主函數(shù)分析
進(jìn)行了上面的操作.有了pdo的配置,有了pdo的時(shí)鐘.萬(wàn)事俱備,只差開(kāi)啟了.?開(kāi)啟發(fā)送只需要在主函數(shù)中調(diào)用模式切換就行:

之后進(jìn)入主while(1)空循環(huán),
程序就會(huì)根據(jù)字典中配置好的5ms周期性發(fā)送pdo1了.

5.查找發(fā)送pdo代碼
調(diào)用setState(&Master_Data, Operational);之后,就會(huì)發(fā)送pdo.
所以,跳入setState(&Master_Data, Operational);函數(shù).
接著跳入switchCommunicationState(d, &newCommunicationState);函數(shù)

接著跳入PDOInit();函數(shù)

接著跳入_sendPDOevent(d,0);


接著跳入sendOnePDOevent(d, pdoNum);

在這里面SetAlarm()函數(shù)是創(chuàng)建軟件定時(shí)器,
有了軟件定時(shí)器,才能是pdo周期性的發(fā)送下去.
(軟件定時(shí)器到期后,會(huì)觸發(fā),PDOEventTimerAlarm();進(jìn)行下次pdo發(fā)送)
這里還有一個(gè)重要的函數(shù)buildPDO(),

接著跳入sendPdo();

canSend函數(shù)就是最后一層了,需要根據(jù)硬件開(kāi)發(fā)環(huán)境編寫(xiě)響應(yīng)的can底層發(fā)送.
以stm32單片機(jī)為例


發(fā)送完成之后,
還有沒(méi)有記得中創(chuàng)建的軟件定時(shí)器,它溢出后,會(huì)執(zhí)行回調(diào)函數(shù),然后準(zhǔn)備下次發(fā)送.

回調(diào)函數(shù)是PDOEventTimerAlarm();