? ? ? ? 在研發(fā)某個(gè)電子產(chǎn)品時(shí),由于需要用到FreeModbus協(xié)議拗胜,所以對(duì)FreeModbus協(xié)議進(jìn)行了系統(tǒng)的自我學(xué)習(xí)蔗候,包括FreeModbus協(xié)議,移植方法等內(nèi)容埂软。前段時(shí)間一直在忙于該產(chǎn)品開(kāi)發(fā)锈遥,所以未及時(shí)的對(duì)其進(jìn)行總結(jié)和歸納,現(xiàn)占用自我的一點(diǎn)休息時(shí)間將FreeModbus的移植方法勘畔、移植時(shí)遇到的一些問(wèn)題及解決方法總結(jié)所灸、歸納一下并分享給大家,借用魯迅的“拿來(lái)主義”思想炫七。希望大家通過(guò)閱讀這篇文章爬立,能夠達(dá)到對(duì)FreeModbus協(xié)議“拿來(lái)就能用”的狀態(tài),與此同時(shí)也希望能夠解答大家的一些疑惑万哪。
一侠驯、為何采用Modbus協(xié)議,而不是自己定義協(xié)議奕巍?
????????Modbus是非常適合嵌入式系統(tǒng)應(yīng)用的一個(gè)通用協(xié)議吟策,既簡(jiǎn)潔又完善。而自己定義的嵌入式協(xié)議的止,一般來(lái)說(shuō)擴(kuò)展性不好檩坚,軟件Bug也比較多。本人始終認(rèn)為站在巨人的肩膀上诅福,我們不但可以走的更遠(yuǎn)匾委,也會(huì)走的更快(即移植成熟的代碼可以減少調(diào)試時(shí)間、提高工作效率)权谁。另外強(qiáng)烈建議在進(jìn)行FreeModbus協(xié)議移植前,最好對(duì)FreeModbus協(xié)議有一個(gè)全面的了解憋沿,可通過(guò)查看或閱讀Modbus協(xié)議說(shuō)明文檔了解旺芽。
二、modbus協(xié)議
????????為了更好的理解辐啄、移植和應(yīng)用FreeModbus協(xié)議采章,個(gè)人覺(jué)得至少應(yīng)該了解以下幾點(diǎn):
????????1、FreeModbus協(xié)議采用主從通訊方式壶辜,支持一個(gè)主機(jī)多個(gè)從機(jī)悯舟,并且遵從一發(fā)一回,不發(fā)不回的通訊原則砸民。
????????2抵怎、FreeModbus協(xié)議傳輸方式采用“大頭字節(jié)”傳輸方式奋救,即是先傳輸高字節(jié)數(shù)據(jù)再傳輸?shù)妥止?jié)數(shù)據(jù)。
????????3反惕、FreeModbus協(xié)議有RTU和ASCII兩種通訊方式尝艘,由于RTU通訊模式的數(shù)據(jù)吞吐量比較大,所以一般會(huì)優(yōu)先考慮采用RTU通訊傳輸模式姿染。
????????4背亥、RTU傳輸幀的格式是:1位起始位、8位數(shù)據(jù)位悬赏、1位校驗(yàn)位狡汉、1位停止位,總共11位闽颇。
????????5盾戴、FreeModbus協(xié)議中沒(méi)有明顯的開(kāi)始符和結(jié)束符,而是通過(guò)幀與幀之間的間隔時(shí)間來(lái)判斷的进萄。如果在指定的時(shí)間內(nèi)沒(méi)有接收到新的字符數(shù)據(jù)捻脖,那么就認(rèn)為收到了新的幀。
????????6、FreeModbus寄存器的地址分為PLC地址和協(xié)議地址盈电,PLC地址為5位十進(jìn)制數(shù)泼舱,比如40001等。協(xié)議地址是去掉PLC地址的最高位矛渴,然后減去1,比如PLC地址為40001惫搏,那么對(duì)于的協(xié)議地址為0x0000(40001為保持寄存器的地址)具温。同一個(gè)協(xié)議地址不同PLC寄存器地址的訪問(wèn)是通過(guò)功能碼來(lái)區(qū)分的,所以不會(huì)存在訪問(wèn)沖突的問(wèn)題筐赔。
????????7铣猩、FreeModbus協(xié)議中有線圈寄存器、離散量寄存器茴丰、保持寄存器和輸入寄存器达皿,注意:線圈和離散量寄存器是位寄存器,保持寄存器為無(wú)符號(hào)16位數(shù)據(jù)贿肩。
? ??????8峦椰、FreeModbus是一種通用的軟件協(xié)議,所有不用擔(dān)心是否能在帶操作系統(tǒng)的嵌入式軟件中移植使用汰规,當(dāng)然裸機(jī)的嵌入式軟件也支持汤功。
三、FreeModbus移植方法
????????下面將以實(shí)際項(xiàng)目中在STM32F4處理器上成功移植的FreeModbus協(xié)議為例分步驟介紹FreeModbus協(xié)議的移植方法:
????????1溜哮、首先去官網(wǎng)下載最新的FreeModbus協(xié)議源碼滔金,本人移植的是FreeModbus-V1.5版本色解。這樣做的好處一方面保證源碼的正確性,另一方面技術(shù)更新?lián)Q代比較快鹦蠕,最新的源碼應(yīng)該是經(jīng)過(guò)多次老版本源碼優(yōu)化的結(jié)果冒签。
????????2、FreeModbus-V1.5解壓后的情況如圖1所示钟病,主要有demo萧恕、modbus、tools肠阱、doc四個(gè)文件夾票唆。其中tools為上位機(jī)測(cè)試modbus程序,doc為一些說(shuō)明文件屹徘。有用的是demo以及modbus走趋。打開(kāi)demo,沒(méi)有看到stm32的工程文件噪伊,有一個(gè)叫BARE的文件夾簿煌,打開(kāi)BARE文件后的情況如圖2所示,是一些不包括任何處理器的部分源代碼鉴吹,我們只需將modbus中的文件姨伟,BARE中port文件中的文件移植到已建的工程中即可。
????????3豆励、FreeModbus協(xié)議的底層移植主要包括串口和定時(shí)器的移植夺荒。定時(shí)器的移植主要有定時(shí)器初始化和35uS定時(shí)中斷函數(shù)等。串口的移植工作主要包括串口的初始化良蒸、發(fā)送和接收中斷函數(shù)技扼,RS485的發(fā)送和接收選擇管腳的初始化和使能函數(shù)等。
????????4嫩痰、FreeModbus協(xié)議的頂層函數(shù)移植主要是線圈的讀寫(xiě)函數(shù)剿吻、離散量的讀函數(shù)、輸入寄存器的度函數(shù)和保持寄存器的讀寫(xiě)函數(shù)等串纺,當(dāng)然還有一些自己編寫(xiě)的解析FreeModbus協(xié)議的函數(shù)丽旅。
四、常見(jiàn)問(wèn)題及解決方法
1造垛、最后一個(gè)字節(jié)發(fā)送不出去的問(wèn)題
(1)問(wèn)題現(xiàn)象:
? ? ? ? FreeModbus移植完成后魔招,首先利用串口調(diào)試助手對(duì)移植的串口通訊情況進(jìn)行了檢查晰搀,通過(guò)觀察串口調(diào)試助手上接收到的數(shù)據(jù)發(fā)現(xiàn)沒(méi)有最后一個(gè)字節(jié)數(shù)據(jù)(測(cè)試程序知道自己要發(fā)送的數(shù)據(jù)內(nèi)容)五辽。
(2)解決方法:
????????出現(xiàn)該問(wèn)題后,首先對(duì)串口的初始化外恕、RS485的發(fā)送和接收使能管腳的初始化進(jìn)行了排查杆逗,發(fā)現(xiàn)的問(wèn)題點(diǎn)1是RS485的發(fā)送接收使能管腳時(shí)鐘沒(méi)有配置正確乡翅,由于采用的是STM32F4系列處理器,GPIO是掛在AHB1總線上的罪郊,所以調(diào)用APB1相關(guān)的處理來(lái)初始化時(shí)鐘是不對(duì)的蠕蚜。出現(xiàn)的問(wèn)題點(diǎn)2是本人使用的是發(fā)送寄存器空中斷導(dǎo)致最后一個(gè)字節(jié)沒(méi)有發(fā)送成功,由于當(dāng)時(shí)項(xiàng)目比較急悔橄,只是在FreeModbus 協(xié)議的源碼中稍微作了修改靶累,實(shí)現(xiàn)最后一個(gè)字節(jié)的數(shù)據(jù)成功發(fā)送。修改地方如圖23所示癣疟。不過(guò)在這里個(gè)人強(qiáng)烈建議使用串口發(fā)送和接收中斷挣柬,一方面可以充分利用MCU的資源,也可以減少等待時(shí)間睛挚;發(fā)送中斷最好用發(fā)送完成中斷邪蛔,如果使用發(fā)送寄存器空中斷,還需要判斷最后一個(gè)字節(jié)數(shù)據(jù)發(fā)送完成與否扎狱,否則導(dǎo)致最后一個(gè)字節(jié)數(shù)據(jù)發(fā)送不出去侧到。
2、PLC地址和協(xié)議地址的問(wèn)題
(1)問(wèn)題現(xiàn)象:
????????FreeModbus移植完成后淤击,利用modbus-poll軟件對(duì)其進(jìn)行調(diào)試時(shí)發(fā)現(xiàn)匠抗,利用自己編寫(xiě)的FreeModbus協(xié)議解析函數(shù)操作0x0001地址時(shí),而對(duì)應(yīng)變化的地址是0x0000遭贸,當(dāng)時(shí)是直接把自己定義的PLC地址的高位給去掉了戈咳。
(2)解決方法:
????????如果您知道FreeModbus協(xié)議有PLC地址和協(xié)議地址之分,并且協(xié)議地址是PLC地址的高位去掉后再減去1的話壕吹,那么這個(gè)問(wèn)題就不是個(gè)什么問(wèn)題著蛙。
3、assert()函數(shù)未定義報(bào)錯(cuò)的問(wèn)題
(1)問(wèn)題現(xiàn)象:
????????FreeModbus移植完成后耳贬,就直接在Keil軟件中對(duì)整個(gè)工程文件進(jìn)行編譯踏堡,編譯后提示assert()未定義。
(2)解決方法:
? ? ? ? 由于之前未遇到過(guò)此類問(wèn)題咒劲,所以去百度上搜索了一下顷蟆,最后經(jīng)過(guò)驗(yàn)證出現(xiàn)此類問(wèn)題的原因是MicroLib不支assert()函數(shù),即是工程文件使用了微庫(kù)腐魂,在target中鉤掉USE MicroLIB后再次編譯通過(guò)帐偎。
五、總結(jié)
????????通過(guò)此次移植FreeModbus協(xié)議蛔屹,并完成對(duì)其的調(diào)試削樊,經(jīng)過(guò)反思覺(jué)得自己還有不足的地方,現(xiàn)就反思的解決問(wèn)題思路進(jìn)行一下歸納和總結(jié),希望對(duì)大家有所幫助漫贞。解決問(wèn)題的思路是:采用先發(fā)散后收斂的問(wèn)題解決思維方式甸箱,發(fā)散就是頭腦風(fēng)暴進(jìn)行各種假設(shè),收斂即是對(duì)出現(xiàn)該問(wèn)題的各種假設(shè)進(jìn)行驗(yàn)證迅脐,逐一排查芍殖,驗(yàn)證方法是采用剝洋蔥式思維。利用Keil的在線調(diào)試技術(shù)進(jìn)行在線實(shí)時(shí)調(diào)試谴蔑,根據(jù)調(diào)試中各個(gè)函數(shù)返回的錯(cuò)誤碼進(jìn)行問(wèn)題排查豌骏,進(jìn)而找到問(wèn)題的根源,最后把問(wèn)題解決掉隐锭。此次移植FreeModbus協(xié)議的解決問(wèn)題心得是:不要一味的假設(shè)肯适,還需要進(jìn)行驗(yàn)證,而驗(yàn)證最好的助手就是儀器儀表成榜,另外能用示波器的地方盡量不用萬(wàn)用表框舔,因?yàn)橥ㄟ^(guò)示波器能夠觀看到信號(hào)變化的整個(gè)過(guò)程,而萬(wàn)用表做不到赎婚。