哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【睿擎派】CANOpen總線之IO模塊讀寫(DS401協(xié)議)

RT-Thread官方賬號(hào) ? 2025-12-24 18:01 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

睿擎派以瑞芯微 RK3506 為主控芯片,底層搭載 RT-Thread 操作系統(tǒng),基于專為工業(yè)場景打造的睿擎工業(yè)平臺(tái)進(jìn)行開發(fā)。該平臺(tái)是全棧自主可控的軟硬件一體化解決方案,整合了數(shù)據(jù)采集、通信、控制、工業(yè)協(xié)議、AI、顯示六大核心功能,精準(zhǔn)適配工業(yè)應(yīng)用需求。


官方僅提供了基于 CANOpen 協(xié)議(即 DS402 設(shè)備規(guī)范)操作伺服電機(jī)的示例代碼,暫無 IO 模塊相關(guān)的操作參考文檔與實(shí)踐案例。經(jīng)過數(shù)日的深入鉆研與反復(fù)調(diào)試,最終成功實(shí)現(xiàn)雷賽 EM32DX-C4 模塊的 IO 信號(hào)采集與輸出控制功能。


下面將簡要分享這段時(shí)間積累的 CANOpen 相關(guān)技術(shù)要點(diǎn),以及代碼編寫與調(diào)試的具體實(shí)踐過程。


一、CANOpen背景知識(shí)介紹

CAN 總線于 1986 年 2 月正式發(fā)布,CANOpen 協(xié)議則在 1994 年 11 月推出。作為基于 CAN 總線的工業(yè)級通信協(xié)議,CANOpen 遵循 EN 50325-4 標(biāo)準(zhǔn),是工業(yè)自動(dòng)化領(lǐng)域主流的現(xiàn)場總線解決方案之一。


其核心優(yōu)勢體現(xiàn)在標(biāo)準(zhǔn)化設(shè)計(jì)上 —— 通過統(tǒng)一的對象字典保障設(shè)備間互操作性,支持 PDO(過程數(shù)據(jù)對象)、SDO(服務(wù)數(shù)據(jù)對象)等靈活通信機(jī)制,兼顧實(shí)時(shí)性與數(shù)據(jù)完整性。協(xié)議內(nèi)置 DS401(IO 模塊)、DS402(運(yùn)動(dòng)控制)等專用行規(guī),可適配伺服電機(jī)、IO 模塊、傳感器等各類工業(yè)設(shè)備。


我們自行生產(chǎn)的網(wǎng)關(guān)產(chǎn)品很早就集成了 CAN 總線功能,但僅用于與自有 IO 模塊的實(shí)時(shí)通信,較少對接第三方模塊。目前國內(nèi)主流智能模塊仍以 RS485 通信為主,我雖早已知曉 CANOpen 協(xié)議,但實(shí)際應(yīng)用機(jī)會(huì)不多。隨著計(jì)劃基于睿賽德睿擎工業(yè)平臺(tái)開發(fā)新一代網(wǎng)關(guān)產(chǎn)品,各類現(xiàn)場工業(yè)總線均需深入研究。


CANOpen 協(xié)議相對復(fù)雜,核心原因是它要求設(shè)備遵循嚴(yán)格的狀態(tài)機(jī)模式,主要包含四大核心狀態(tài):

(1) 初始化狀態(tài)(Initialization)

設(shè)備剛上電,正在進(jìn)行硬件自檢和協(xié)議棧初始化

不參與網(wǎng)絡(luò)通信,不接收任何命令 (除基本復(fù)位)

完成后自動(dòng)進(jìn)入 Pre-operational 狀態(tài),并發(fā)送一個(gè)啟動(dòng)心跳信號(hào)

(2) 預(yù)操作狀態(tài)(Pre-operationa)

設(shè)備已初始化完成,等待配置

可接收 SDO (服務(wù)數(shù)據(jù)對象),進(jìn)行參數(shù)配置和診斷

PDO (過程數(shù)據(jù)對象) 通信被禁用,無法進(jìn)行正常數(shù)據(jù)交換

是唯一可修改對象字典的狀態(tài),適合設(shè)備參數(shù)配置

(3) 操作狀態(tài)(Operational)

設(shè)備正常工作狀態(tài),所有功能激活

PDO 和 SDO 通信全部啟用,可收發(fā)過程數(shù)據(jù)

設(shè)備自主執(zhí)行任務(wù),響應(yīng)網(wǎng)絡(luò)請求

由 NMT 主機(jī)發(fā)送 “Start Node” 命令觸發(fā)進(jìn)入

(4) 停止?fàn)顟B(tài)(Stopped)

設(shè)備的安全狀態(tài),功能受到限制。

PDO 通信被完全禁用,僅允許 NMT 命令和心跳

設(shè)備保持配置,但不執(zhí)行控制任務(wù)

由 NMT 主機(jī)發(fā)送 “Stop Node” 命令觸發(fā),常用于安全暫停

75fa02f6-e0af-11f0-8ce9-92fbcf53809c.png


注:對伺服運(yùn)動(dòng)設(shè)備(DS402),還額外定義了電源相關(guān)狀態(tài),比如電源禁用區(qū),電源啟用區(qū),故障區(qū)等相關(guān)定義。


CANOpen 協(xié)議的四大核心狀態(tài)中,嵌套了三種核心通信模型,具體如下:

(1) 主 / 從站模型:與 Modbus 協(xié)議邏輯類似,核心差異是支持多主機(jī)架構(gòu),最多可接入 127 個(gè)從站,主要用于網(wǎng)絡(luò)診斷和設(shè)備狀態(tài)管理。

(2) 客戶端 / 服務(wù)器模型:借鑒 TCP/IP 協(xié)議的交互模式,專門適配對象字典(OD)的讀寫操作。從設(shè)備作為服務(wù)器提供參數(shù)訪問服務(wù),主設(shè)備作為客戶端發(fā)起讀寫請求。

(3) 生產(chǎn)者 / 消費(fèi)者模型:與 MQTT 協(xié)議的通信邏輯一致,從設(shè)備擔(dān)任數(shù)據(jù)生產(chǎn)者,主設(shè)備擔(dān)任數(shù)據(jù)消費(fèi)者。生產(chǎn)者可按主設(shè)備的明確請求(拉模型),或主動(dòng)無請求推送(推模型),傳輸預(yù)設(shè)的目標(biāo)數(shù)據(jù)。


了解了以上知識(shí)后,還需要了解CANOpen協(xié)議的如下相關(guān)概念

(1) 對象字典

對象字典的功能類似 Modbus 協(xié)議中的寄存器,是定義 CANOpen 節(jié)點(diǎn)所有行為、參數(shù)及通信規(guī)則的核心。與 Modbus 寄存器不同,它通過 “16 位索引 + 8 位子索引” 的雙標(biāo)識(shí)方式,唯一確定每個(gè)條目。

對象字典分為公共對象字典和私有對象字典。其中 DS301 協(xié)議作為 CANOpen 的基礎(chǔ)通用協(xié)議,明確了所有 CANOpen 設(shè)備必須遵循的公共對象字典規(guī)范。

760b3ca6-e0af-11f0-8ce9-92fbcf53809c.png


針對我們對接的EM32DX-C4查看設(shè)備手冊,DS301對應(yīng)的數(shù)據(jù)字典的通用參數(shù)如下:

76133578-e0af-11f0-8ce9-92fbcf53809c.png


設(shè)備參數(shù)如下:

7624d846-e0af-11f0-8ce9-92fbcf53809c.png


DS401屬于子協(xié)議,專門定義數(shù)字量 / 模擬量 IO 的采集、控制、診斷等特有功能,索引范圍集中在 0x6000-0x77FF,核心條目按 “數(shù)字量 IO”“模擬量 IO”“診斷” 分類


76321a74-e0af-11f0-8ce9-92fbcf53809c.png


查EM32DX-C4設(shè)備手冊 DS401協(xié)議對應(yīng)的對象字典參數(shù)如下:

7644997e-e0af-11f0-8ce9-92fbcf53809c.png


(2) COB-ID

COB-ID其實(shí)就是11位CAN ID,它分兩部分組成,高4位為功能碼,低7位為從設(shè)備地址碼,所以最多支持127個(gè)從設(shè)備。

764cfb32-e0af-11f0-8ce9-92fbcf53809c.png


功能碼和具體的通信服務(wù)相關(guān)(如下圖所示):

765bc0b8-e0af-11f0-8ce9-92fbcf53809c.jpg


(3) 網(wǎng)絡(luò)管理(NMT)

NMT服務(wù)用于通過NMT命令(如:啟動(dòng)、停止、復(fù)位)來控制CANopen設(shè)備的狀態(tài)(如:預(yù)運(yùn)行、運(yùn)行、停止)。

為了改變狀態(tài),NMT主機(jī)發(fā)送一個(gè)帶有 CAN ID 的2字節(jié)消息(即功能代碼和節(jié)點(diǎn)ID )。所有從站節(jié)點(diǎn)都處理這個(gè)報(bào)文。節(jié)點(diǎn)ID 0表示廣播命令。


766aa2b8-e0af-11f0-8ce9-92fbcf53809c.png


功能代碼如下:

766aa2b8-e0af-11f0-8ce9-92fbcf53809c.png


(4) 服務(wù)數(shù)據(jù)對象(SDO)

SDO(Server Data Object,服務(wù)數(shù)據(jù)對象)的核心功能是訪問或修改 CANopen 設(shè)備對象字典內(nèi)的參數(shù)值。例如,當(dāng)應(yīng)用主站需調(diào)整 CANopen 設(shè)備的特定配置參數(shù)時(shí),可借助 SDO 服務(wù)完成參數(shù)的讀寫操作,實(shí)現(xiàn)設(shè)備配置的靈活變更。

(5) 過程數(shù)據(jù)對象(PDO)

PDO(Process Data Object,過程數(shù)據(jù)對象) 是專為設(shè)備間實(shí)時(shí)、高速數(shù)據(jù)傳輸設(shè)計(jì)的核心通信服務(wù),是工業(yè)場景中過程數(shù)據(jù)交互的關(guān)鍵通道。

PDO數(shù)據(jù)上傳有四種方式觸發(fā):

定時(shí)發(fā)送,同步傳輸(同步信號(hào)觸發(fā)),遠(yuǎn)程請求和事件觸發(fā)。

(6) 心跳信號(hào)(Heartbeat)

CANopen 的心跳服務(wù)具有雙重核心目的:一是向網(wǎng)絡(luò)發(fā)送 “設(shè)備在線” 的活動(dòng)消息,二是確認(rèn) NMT 命令的執(zhí)行狀態(tài)。NMT 從設(shè)備會(huì)按預(yù)設(shè)周期(例如 200 毫秒)發(fā)送心跳消息,消息 CAN ID 遵循固定規(guī)則(如節(jié)點(diǎn) 2 的 CAN ID 為 0x702),其第一個(gè)數(shù)據(jù)字節(jié)攜帶節(jié)點(diǎn)當(dāng)前的 NMT 狀態(tài)碼(如下圖)。若心跳消息的接收方(如NMT主站)在設(shè)定時(shí)限內(nèi)未收到該消息,將觸發(fā)預(yù)設(shè)的離線響應(yīng)機(jī)制。

76897936-e0af-11f0-8ce9-92fbcf53809c.png

(7) 同步(SYNC)

CANopen 的 SYNC 報(bào)文核心作用是同步多個(gè)從設(shè)備的輸入采集與輸出響應(yīng),通常由應(yīng)用主站發(fā)起。主站向 CANopen 網(wǎng)絡(luò)發(fā)送 SYNC 消息(COB-ID 為 0x080),支持帶或不帶 SYNC 計(jì)數(shù)器兩種傳輸形式。多個(gè)從節(jié)點(diǎn)可預(yù)先配置為響應(yīng) SYNC 信號(hào),要么同步捕獲輸入數(shù)據(jù)并傳輸,要么與其他參與同步的節(jié)點(diǎn)協(xié)同設(shè)置輸出,確保動(dòng)作一致性。

SYNC 計(jì)數(shù)器的存在可靈活劃分同步組,實(shí)現(xiàn)多組設(shè)備的獨(dú)立同步操作,適配不同場景下的協(xié)同需求。

(8) 緊急情況(EMCY)

CANopen 的緊急服務(wù)(EMCY)專為設(shè)備發(fā)生致命錯(cuò)誤(如傳感器故障)設(shè)計(jì),用于向網(wǎng)絡(luò)其他節(jié)點(diǎn)及時(shí)上報(bào)故障狀態(tài)。受影響的節(jié)點(diǎn)會(huì)以高優(yōu)先級、單次觸發(fā)式向網(wǎng)絡(luò)發(fā)送 EMCY 消息(例如節(jié)點(diǎn) 2 的消息 COB-ID 為 0x082)。消息的數(shù)據(jù)字節(jié)攜帶具體錯(cuò)誤碼及相關(guān)輔助信息,通過查詢設(shè)備手冊或協(xié)議規(guī)范,可獲取對應(yīng)的故障詳情。

(9) 時(shí)間戳(Timestamp)

該消息由主站發(fā)起,對應(yīng)的 CAN ID 為 0x100。使用 6 字節(jié) (48 位)表示。前 4 個(gè)字節(jié) (32 位): 表示從午夜開始的毫秒數(shù)(范圍: 0-4294967295 毫秒,約 1193 小時(shí))。后 2 個(gè)字節(jié) (16 位): 表示自 1984 年 1 月 1 日 0 時(shí)起的天數(shù)(范圍: 0-65535 天,約 179.4 年) 。


二、CANOpen DS401協(xié)議實(shí)現(xiàn)


官方示例(06_bus_canopen_master_motor)在免費(fèi)開源的CanFestival(LGPLv2 許可證)的基礎(chǔ)上實(shí)現(xiàn)的。該開源代碼實(shí)現(xiàn)了CANOpen協(xié)議如下功能:

(1)NMT(網(wǎng)絡(luò)管理):節(jié)點(diǎn)狀態(tài)控制(初始化、預(yù)操作、操作、停止)和心跳監(jiān)測

(2)PDO(過程數(shù)據(jù)對象):高速實(shí)時(shí)數(shù)據(jù)傳輸,支持循環(huán)和事件觸發(fā)模式,優(yōu)化工業(yè)控制場景響應(yīng)速度

(3)SDO(服務(wù)數(shù)據(jù)對象):對象字典參數(shù)訪問,支持快速下載和分段下載,用于設(shè)備配置和參數(shù)調(diào)整

(4)SYNC(同步對象):網(wǎng)絡(luò)時(shí)鐘同步和周期性數(shù)據(jù)傳輸協(xié)調(diào)

(5)EMCY(緊急對象):錯(cuò)誤報(bào)告和故障通知機(jī)制


769924f8-e0af-11f0-8ce9-92fbcf53809c.jpg


我是在官方示例06_bus_canopen_master_motor的基礎(chǔ)上進(jìn)行大幅度修改而完成。除了canopen_callback.*相關(guān)內(nèi)容沒有多少變化外,其他文件改動(dòng)比較大。

講解代碼之前,先簡單說一下硬件接線。查EM32DX-C4手冊,CANOpen接口采用了以太網(wǎng)的接口,管腳定義如下:

76a10880-e0af-11f0-8ce9-92fbcf53809c.jpg


根據(jù)這個(gè)定義,自己做了一個(gè)CAN網(wǎng)絡(luò)連接線,主要用到1,2兩根線,對應(yīng)的網(wǎng)線是1-白橙和2-橙色。白橙也就是CAN_P接入睿擎派的CAN_H接口,橙色接入睿擎派的CAN_L接口。


76b377f4-e0af-11f0-8ce9-92fbcf53809c.jpg


由于我對 CANOpen 協(xié)議的了解不夠深入,且是初次接觸塞雷 EM32DX-C4 硬件模塊,初期的調(diào)試工作遇到了不少阻礙。好在手頭恰好有 PCAN-USB 模塊,將其接入 CAN 總線后,我通過 PCAN-View 工具實(shí)時(shí)監(jiān)聽 CAN 幀數(shù)據(jù),這一操作直接顯著提升了開發(fā)與調(diào)試的效率(如下圖)。


76c43a94-e0af-11f0-8ce9-92fbcf53809c.png


master402_od.c改名為master401_od.c

主要是DS301和DS401對象字典定義的地方。對原有的數(shù)據(jù)字典進(jìn)行了大幅度的刪減。

原有的對象字典定義:

const indextable master402_objdict[] ={ { (subindex*)master402_Index1000,sizeof(master402_Index1000)/sizeof(master402_Index1000[0]), 0x1000}, { (subindex*)master402_Index1001,sizeof(master402_Index1001)/sizeof(master402_Index1001[0]), 0x1001}, { (subindex*)master402_Index1005,sizeof(master402_Index1005)/sizeof(master402_Index1005[0]), 0x1005}, { (subindex*)master402_Index1006,sizeof(master402_Index1006)/sizeof(master402_Index1006[0]), 0x1006}, { (subindex*)master402_Index1014,sizeof(master402_Index1014)/sizeof(master402_Index1014[0]), 0x1014}, { (subindex*)master402_Index1016,sizeof(master402_Index1016)/sizeof(master402_Index1016[0]), 0x1016}, { (subindex*)master402_Index1017,sizeof(master402_Index1017)/sizeof(master402_Index1017[0]), 0x1017}, { (subindex*)master402_Index1018,sizeof(master402_Index1018)/sizeof(master402_Index1018[0]), 0x1018}, { (subindex*)master402_Index1200,sizeof(master402_Index1200)/sizeof(master402_Index1200[0]), 0x1200}, { (subindex*)master402_Index1280,sizeof(master402_Index1280)/sizeof(master402_Index1280[0]), 0x1280}, { (subindex*)master402_Index1281,sizeof(master402_Index1281)/sizeof(master402_Index1281[0]), 0x1281}, { (subindex*)master402_Index1400,sizeof(master402_Index1400)/sizeof(master402_Index1400[0]), 0x1400}, { (subindex*)master402_Index1401,sizeof(master402_Index1401)/sizeof(master402_Index1401[0]), 0x1401}, { (subindex*)master402_Index1402,sizeof(master402_Index1402)/sizeof(master402_Index1402[0]), 0x1402}, { (subindex*)master402_Index1403,sizeof(master402_Index1403)/sizeof(master402_Index1403[0]), 0x1403}, { (subindex*)master402_Index1600,sizeof(master402_Index1600)/sizeof(master402_Index1600[0]), 0x1600}, { (subindex*)master402_Index1601,sizeof(master402_Index1601)/sizeof(master402_Index1601[0]), 0x1601}, { (subindex*)master402_Index1602,sizeof(master402_Index1602)/sizeof(master402_Index1602[0]), 0x1602}, { (subindex*)master402_Index1603,sizeof(master402_Index1603)/sizeof(master402_Index1603[0]), 0x1603}, { (subindex*)master402_Index1800,sizeof(master402_Index1800)/sizeof(master402_Index1800[0]), 0x1800}, { (subindex*)master402_Index1801,sizeof(master402_Index1801)/sizeof(master402_Index1801[0]), 0x1801}, { (subindex*)master402_Index1802,sizeof(master402_Index1802)/sizeof(master402_Index1802[0]), 0x1802}, { (subindex*)master402_Index1803,sizeof(master402_Index1803)/sizeof(master402_Index1803[0]), 0x1803}, { (subindex*)master402_Index1A00,sizeof(master402_Index1A00)/sizeof(master402_Index1A00[0]), 0x1A00}, { (subindex*)master402_Index1A01,sizeof(master402_Index1A01)/sizeof(master402_Index1A01[0]), 0x1A01}, { (subindex*)master402_Index1A02,sizeof(master402_Index1A02)/sizeof(master402_Index1A02[0]), 0x1A02}, { (subindex*)master402_Index1A03,sizeof(master402_Index1A03)/sizeof(master402_Index1A03[0]), 0x1A03}, { (subindex*)master402_Index2001,sizeof(master402_Index2001)/sizeof(master402_Index2001[0]), 0x2001}, { (subindex*)master402_Index2002,sizeof(master402_Index2002)/sizeof(master402_Index2002[0]), 0x2002}, { (subindex*)master402_Index2003,sizeof(master402_Index2003)/sizeof(master402_Index2003[0]), 0x2003}, { (subindex*)master402_Index2004,sizeof(master402_Index2004)/sizeof(master402_Index2004[0]), 0x2004}, { (subindex*)master402_Index2005,sizeof(master402_Index2005)/sizeof(master402_Index2005[0]), 0x2005}, { (subindex*)master402_Index2006,sizeof(master402_Index2006)/sizeof(master402_Index2006[0]), 0x2006}, { (subindex*)master402_Index2007,sizeof(master402_Index2007)/sizeof(master402_Index2007[0]), 0x2007}, { (subindex*)master402_Index2124,sizeof(master402_Index2124)/sizeof(master402_Index2124[0]), 0x2124}, { (subindex*)master402_Index2F00,sizeof(master402_Index2F00)/sizeof(master402_Index2F00[0]), 0x2F00}, { (subindex*)master402_Index2F01,sizeof(master402_Index2F01)/sizeof(master402_Index2F01[0]), 0x2F01}, { (subindex*)master402_Index6040,sizeof(master402_Index6040)/sizeof(master402_Index6040[0]), 0x6040}, { (subindex*)master402_Index6041,sizeof(master402_Index6041)/sizeof(master402_Index6041[0]), 0x6041}, { (subindex*)master402_Index6060,sizeof(master402_Index6060)/sizeof(master402_Index6060[0]), 0x6060}, { (subindex*)master402_Index6064,sizeof(master402_Index6064)/sizeof(master402_Index6064[0]), 0x6064}, { (subindex*)master402_Index606C,sizeof(master402_Index606C)/sizeof(master402_Index606C[0]), 0x606C}, { (subindex*)master402_Index607A,sizeof(master402_Index607A)/sizeof(master402_Index607A[0]), 0x607A}, { (subindex*)master402_Index607C,sizeof(master402_Index607C)/sizeof(master402_Index607C[0]), 0x607C}, { (subindex*)master402_Index6081,sizeof(master402_Index6081)/sizeof(master402_Index6081[0]), 0x6081}, { (subindex*)master402_Index6098,sizeof(master402_Index6098)/sizeof(master402_Index6098[0]), 0x6098}, { (subindex*)master402_Index6099,sizeof(master402_Index6099)/sizeof(master402_Index6099[0]), 0x6099}, { (subindex*)master402_Index60C1,sizeof(master402_Index60C1)/sizeof(master402_Index60C1[0]), 0x60C1}, { (subindex*)master402_Index60C2,sizeof(master402_Index60C2)/sizeof(master402_Index60C2[0]), 0x60C2}, { (subindex*)master402_Index60FF,sizeof(master402_Index60FF)/sizeof(master402_Index60FF[0]), 0x60FF},};

刪減后的對象字典定義:

const indextable master401_objdict[] ={ { (subindex*)master401_Index1000,sizeof(master401_Index1000)/sizeof(master401_Index1000[0]), 0x1000}, { (subindex*)master401_Index1001,sizeof(master401_Index1001)/sizeof(master401_Index1001[0]), 0x1001}, { (subindex*)master401_Index1005,sizeof(master401_Index1005)/sizeof(master401_Index1005[0]), 0x1005}, { (subindex*)master401_Index1006,sizeof(master401_Index1006)/sizeof(master401_Index1006[0]), 0x1006}, { (subindex*)master401_Index1014,sizeof(master401_Index1014)/sizeof(master401_Index1014[0]), 0x1014}, { (subindex*)master401_Index1016,sizeof(master401_Index1016)/sizeof(master401_Index1016[0]), 0x1016}, { (subindex*)master401_Index1017,sizeof(master401_Index1017)/sizeof(master401_Index1017[0]), 0x1017}, { (subindex*)master401_Index1018,sizeof(master401_Index1018)/sizeof(master401_Index1018[0]), 0x1018}, { (subindex*)master401_Index1200,sizeof(master401_Index1200)/sizeof(master401_Index1200[0]), 0x1200}, { (subindex*)master401_Index1280,sizeof(master401_Index1280)/sizeof(master401_Index1280[0]), 0x1280}, { (subindex*)master401_Index1400,sizeof(master401_Index1400)/sizeof(master401_Index1400[0]), 0x1400}, { (subindex*)master401_Index1600,sizeof(master401_Index1600)/sizeof(master401_Index1600[0]), 0x1600}, { (subindex*)master401_Index1800,sizeof(master401_Index1800)/sizeof(master401_Index1800[0]), 0x1800}, { (subindex*)master401_Index1A00,sizeof(master401_Index1A00)/sizeof(master401_Index1A00[0]), 0x1A00}, { (subindex*)master401_Index2000,sizeof(master401_Index2000)/sizeof(master401_Index2000[0]), 0x2000}, { (subindex*)master401_Index2001,sizeof(master401_Index2001)/sizeof(master401_Index2001[0]), 0x2001},};

相比原有代碼,增加了DO和DI相關(guān)的對象字典的定義:

/* -------------------------- 0x2000 本地DO輸出緩存 -------------------------- */// 子索引0:最高子索引編號(hào)(=1,因?yàn)橛?個(gè)子索引:0和1)// 子索引1:實(shí)際DO數(shù)據(jù)存儲(chǔ)(uint16,RW)UNS8 master401_highestSubIndex_obj2000 =1; /* 最高子索引編號(hào) = 子索引數(shù)量-1 */uint16_tmaster401_obj2000_do_val =0x0000; /* DO數(shù)據(jù)存儲(chǔ)變量(關(guān)聯(lián)g_em32dx_do)*/subindex master401_Index2000[] ={ // 子索引0:聲明最高子索引編號(hào)(RO,不可寫) { RO, uint8,sizeof(UNS8), (void*)&master401_highestSubIndex_obj2000,NULL}, // 子索引1:實(shí)際DO數(shù)據(jù)(RW,uint16) { RW, uint16,sizeof(uint16_t), (void*)&master401_obj2000_do_val,NULL}};/* -------------------------- 0x2001 本地DI輸入緩存 -------------------------- */// 子索引0:最高子索引編號(hào)(=1)// 子索引1:實(shí)際DI數(shù)據(jù)存儲(chǔ)(uint16,RO)UNS8 master401_highestSubIndex_obj2001 =1; /* 最高子索引編號(hào) = 子索引數(shù)量-1 */uint16_tmaster401_obj2001_di_val =0x0000; /* DI數(shù)據(jù)存儲(chǔ)變量(關(guān)聯(lián)g_em32dx_di)*/subindex master401_Index2001[] ={ // 子索引0:聲明最高子索引編號(hào)(RO,不可寫) { RO, uint8,sizeof(UNS8), (void*)&master401_highestSubIndex_obj2001,NULL}, // 子索引1:實(shí)際DI數(shù)據(jù)(RO,uint16,協(xié)議棧自動(dòng)更新) { RO, uint16,sizeof(uint16_t), (void*)&master401_obj2001_di_val,NULL}};

需要特別注意的是,master401_od.c中定義的對象字典僅適用于主設(shè)備 —— 這是我初期的核心困惑點(diǎn),曾誤以為主設(shè)備無需額外定義對象字典。且主設(shè)備對象字典中0x1400、0x1800 索引的含義,與從設(shè)備對應(yīng)索引的描述恰好相反:具體來說,主設(shè)備的 TPDO1(發(fā)送過程數(shù)據(jù)對象 1)對應(yīng)從設(shè)備的 RPDO1(接收過程數(shù)據(jù)對象 1),而主設(shè)備的 RPDO1 則對應(yīng)從設(shè)備的 TPDO1。


文件調(diào)整方面:已移除motor_control.c與motor_control.h文件,并將原文件中的相關(guān) IO 操作整合至master401_canopen.c中;同時(shí)將原master402_canopen.c文件重命名為master401_canopen.c,且對文件內(nèi)大部分核心代碼進(jìn)行了適配性修改。


從設(shè)備 IO 模塊的對象字典配置,均在該文件中完成實(shí)現(xiàn),具體代碼如下:

/************************** 核心修改:IO模塊PDO映射配置 **************************/// 說明:// - 從站(EM32DX-C4)接收DO輸出:RPDO1(0x1400)映射DO0-DO15(2字節(jié))// - 從站(EM32DX-C4)發(fā)送DI輸入:TPDO1(0x1800)映射DI0-DI15(2字節(jié))// - 復(fù)用原PDO通道,刪除伺服相關(guān)映射/* TPDO1配置(從站→主站:DI輸入)*/staticUNS8IO_DIS_SLAVE_TPDO1(uint8_tnodeId){ rt_kprintf("config...0!\n"); UNS32 TPDO_COBId =PDO_DISANBLE(0x00000180, nodeId); // COB-ID: 0x182(IO_NODEID=2) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1800,1,4, uint32, &TPDO_COBId, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_TPDO1_Type(uint8_tnodeId){ rt_kprintf("config...1!\n"); UNS8 trans_type = PDO_TRANSMISSION_TYPE; // 同步傳輸 returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1800,2,1, uint8, &trans_type, config_node_param_cb,0);}staticUNS8IO_Clear_SLAVE_TPDO1_Cnt(uint8_tnodeId){ rt_kprintf("config...2!\n"); UNS8 pdo_map_cnt =0; // 清除原有映射 returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1A00,0,1, uint8, &pdo_map_cnt, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_TPDO1_Map(uint8_tnodeId){ rt_kprintf("config...3!\n"); // TPDO1映射:DI0-DI15(模塊DI對應(yīng)索引0x6100,子索引0x01,2字節(jié)) UNS32 pdo_map_val =0x61000110; // 索引0x6100 + 子索引0x01 + 16位長度(0x10) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1A00,1,4, uint32, &pdo_map_val, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_TPDO1_Cnt(uint8_tnodeId){ rt_kprintf("config...4!\n"); UNS8 pdo_map_cnt =1; // 1個(gè)映射項(xiàng)(2字節(jié)) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1A00,0,1, uint8, &pdo_map_cnt, config_node_param_cb,0);}staticUNS8IO_EN_SLAVE_TPDO1(uint8_tnodeId){ rt_kprintf("config...5!\n"); UNS32 TPDO_COBId =PDO_ENANBLE(0x00000180, nodeId); returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1800,1,4, uint32, &TPDO_COBId, config_node_param_cb,0);}//-----------------------------------------------------------///* RPDO1配置(主站→從站:DO輸出)*/staticUNS8IO_DIS_SLAVE_RPDO1(uint8_tnodeId){ rt_kprintf("config...6!\n"); UNS32 RPDO_COBId =PDO_DISANBLE(0x00000200, nodeId); // COB-ID: 0x202(IO_NODEID=2) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1400,1,4, uint32, &RPDO_COBId, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_RPDO1_Type(uint8_tnodeId){ rt_kprintf("config...7!\n"); UNS8 trans_type = PDO_TRANSMISSION_TYPE; // 同步傳輸 returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1400,2,1, uint8, &trans_type, config_node_param_cb,0);}staticUNS8IO_Clear_SLAVE_RPDO1_Cnt(uint8_tnodeId){ rt_kprintf("config...8!\n"); UNS8 pdo_map_cnt =0; // 清除原有映射 returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1600,0,1, uint8, &pdo_map_cnt, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_RPDO1_Map(uint8_tnodeId){ rt_kprintf("config...9!\n"); // RPDO1映射:DO0-DO15(模塊DO對應(yīng)索引0x6300,子索引0x01,2字節(jié)) UNS32 pdo_map_val =0x63000110; // 索引0x6300 + 子索引0x01 + 16位長度(0x10) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1600,1,4, uint32, &pdo_map_val, config_node_param_cb,0);}staticUNS8IO_Write_SLAVE_RPDO1_Cnt(uint8_tnodeId){ rt_kprintf("config...10!\n"); UNS8 pdo_map_cnt =1; // 1個(gè)映射項(xiàng)(2字節(jié)) returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1600,0,1, uint8, &pdo_map_cnt, config_node_param_cb,0);}staticUNS8IO_EN_SLAVE_RPDO1(uint8_tnodeId){ rt_kprintf("config...11!\n"); UNS32 RPDO_COBId =PDO_ENANBLE(0x00000200, nodeId); returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1400,1,4, uint32, &RPDO_COBId, config_node_param_cb,0);}//-----------------------------------------------------------///* 心跳配置(IO模塊生產(chǎn)者心跳)*/staticUNS8IO_Write_SLAVE_Heartbeat(uint8_tnodeId){ rt_kprintf("config...12!\n"); UNS16 producer_heartbeat_time = PRODUCER_HEARTBEAT_TIME; returnwriteNetworkDictCallBack(OD_Data, nodeId,0x1017,0,2, uint16, &producer_heartbeat_time, config_node_param_cb,0);}/* 配置完成回調(diào) */staticUNS8IO_Config_Done(uint8_tnodeId){ rt_kprintf("config...13!\n"); node_config_state *conf = &slave_conf; rt_sem_release(&(conf->finish_sem)); return0;}// IO模塊配置函數(shù)指針數(shù)組(按順序執(zhí)行)staticUNS8(*IOCFG_Operation[])(uint8_tnodeId)= { // TPDO1(DI輸入)配置(6步) IO_DIS_SLAVE_TPDO1, // 步驟0:禁用TPDO1 IO_Write_SLAVE_TPDO1_Type,// 步驟1:寫TPDO1傳輸類型 IO_Clear_SLAVE_TPDO1_Cnt, // 步驟2:清除TPDO1映射數(shù) IO_Write_SLAVE_TPDO1_Map, // 步驟3:寫TPDO1映射 IO_Write_SLAVE_TPDO1_Cnt, // 步驟4:設(shè)置TPDO1映射數(shù) IO_EN_SLAVE_TPDO1, // 步驟5:啟用TPDO1 // RPDO1(DO輸出)配置(6步) IO_DIS_SLAVE_RPDO1, // 步驟6:禁用RPDO1 IO_Write_SLAVE_RPDO1_Type,// 步驟7:寫RPDO1傳輸類型 IO_Clear_SLAVE_RPDO1_Cnt, // 步驟8:清除RPDO1映射數(shù) IO_Write_SLAVE_RPDO1_Map, // 步驟9:寫RPDO1映射 IO_Write_SLAVE_RPDO1_Cnt, // 步驟10:設(shè)置RPDO1映射數(shù) IO_EN_SLAVE_RPDO1, // 步驟11:啟用RPDO1 // 心跳配置(1步) IO_Write_SLAVE_Heartbeat, // 步驟12:寫從站心跳 // 配置完成(1步) IO_Config_Done, // 步驟13:釋放信號(hào)量};

原先DS301一些邏輯我們進(jìn)行了保留。

并且新增了一些 IO操作接口函數(shù),代碼如下:

/************************** 新增IO操作API(上層調(diào)用) **************************//***@brief設(shè)置EM32DX-C4的DO輸出*@paramdo_val: 16位DO值(bit0=DO0, bit15=DO15,1=導(dǎo)通,0=斷開)*@retvalRT_EOK: 成功,-RT_ERROR: 失敗*/rt_err_tem32dx_set_do(uint16_t do_val){ if(*can_node[1].nmt_state != Operational) { rt_kprintf("EM32DX-C4 not in Operational state!\n"); return-RT_ERROR; } // 更新全局緩存 g_em32dx_do = do_val; // 通過RPDO1發(fā)送DO值 UNS32size=2; UNS32errorCode=writeLocalDict(OD_Data,0x2000,1, &do_val, &size,0); if(errorCode != OD_SUCCESSFUL) { rt_kprintf("Write DO failed! Error code: 0x%08X\n", errorCode); return-RT_ERROR; } returnRT_EOK;}/***@brief讀取EM32DX-C4的DI輸入*@paramdi_val: 輸出參數(shù),存儲(chǔ)16位DI值(bit0=DI0, bit15=DI15,1=導(dǎo)通,0=斷開)*@retvalRT_EOK: 成功,-RT_ERROR: 失敗*/rt_err_tem32dx_get_di(){ if(*can_node[1].nmt_state != Operational) { rt_kprintf("EM32DX-C4 not ready!\n"); return-RT_ERROR; } // 從本地字典讀取TPDO1接收的DI值 uint16_tdi_val=0; UNS32size=2; UNS8 data_type; UNS32errorCode=readLocalDict(OD_Data,0x2001,1, &di_val, &size, &data_type,0); if(errorCode != OD_SUCCESSFUL) { rt_kprintf("Read DI failed! Error code: 0x%08X\n", errorCode); return-RT_ERROR; } rt_kprintf("Read DI: 0x%04X\n", di_val); // 更新全局緩存 g_em32dx_di = di_val; returnRT_EOK;}MSH_CMD_EXPORT(em32dx_get_di, Get EM32DX-C4 DI input);/***@brief單獨(dú)控制某一路DO*@paramchannel: DO通道(0-15)*@paramstate: 0=斷開,1=導(dǎo)通*@retvalRT_EOK: 成功,-RT_ERROR: 失敗*/rt_err_tem32dx_set_do_channel(uint8_t argc,char**argv){ if(argc =16) { rt_kprintf("DO channel out of range (0-15)!\n"); return-RT_ERROR; } if(state) { g_em32dx_do |= (1<< channel);? ? }?else?{? ? ? ? g_em32dx_do &= ~(1?<< channel);? ? }? ? return?em32dx_set_do(g_em32dx_do);}MSH_CMD_EXPORT(em32dx_set_do_channel, Set single DO?channel?(channel?0-15, state?0/1));


代碼編譯完成后,我們將其部署至睿擎派,具體操作步驟如下:

(1)執(zhí)行 canopen_start 指令,完成 CANOpen 服務(wù)的初始化與啟動(dòng);

(2)執(zhí)行 em32dx_get_di 指令,獲取 16 路開關(guān)量的當(dāng)前狀態(tài);

(3)執(zhí)行 em32dx_set_do_channel 1 1 指令,配置 16 路 DO 通道的輸出狀態(tài)。

其中第一個(gè)參數(shù)為通道索引(取值范圍:0–15),第二個(gè)參數(shù)為輸出狀態(tài)(0 = 關(guān)閉,1 = 打開)。


76d27686-e0af-11f0-8ce9-92fbcf53809c.png76da88bc-e0af-11f0-8ce9-92fbcf53809c.png


上述指令執(zhí)行完成后,我們可以觀察到對應(yīng)的 DO 通道狀態(tài)指示燈,會(huì)同步呈現(xiàn)出預(yù)期的狀態(tài)變化(與指令配置的輸出狀態(tài)一致)。


76e917e2-e0af-11f0-8ce9-92fbcf53809c.png



源代碼下載鏈接:

鏈接:https://pan.baidu.com/s/1aZDxzb3NNhn3WRBA4OeN4w?pwd=w8au

提取碼: w8au


附錄:

(1)CANOpen DS301、DS302、DS401、DS402等全套協(xié)議下載:

https://link.gitcode.com/i/614ed2a5064e1990bff8ffcde2328ada?uuid_tt_dd=10_19283516180-1733805088376-790686&isLogin=1&from_id=142936482


(2)DS301協(xié)議中文版

https://files.cnblogs.com/files/winshton/301_v04020005_cn_v02_ro.pdf

https://winshton.gitbooks.io/canopen-ds301-cn/content/


————————————————


版權(quán)聲明:本文為RT-Thread論壇用戶「yefanqiu」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。


原文鏈接:

https://club.rt-thread.org/ask/article/bb8a52de0882d43b.html


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • CAN
    CAN
    +關(guān)注

    關(guān)注

    59

    文章

    3091

    瀏覽量

    473317
  • 總線
    +關(guān)注

    關(guān)注

    10

    文章

    3052

    瀏覽量

    91841
  • RT-Thread
    +關(guān)注

    關(guān)注

    32

    文章

    1634

    瀏覽量

    45140
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于輕松玩轉(zhuǎn)CANopen電機(jī)控制

    在工業(yè)自動(dòng)化領(lǐng)域,穩(wěn)定高效的設(shè)備間通信是核心。CANopen協(xié)議憑借其可靠性,成為眾多工業(yè)設(shè)備(如伺服電機(jī))的首選通信標(biāo)準(zhǔn)。今天,我們就來展示如何利用RT-Thread工業(yè)開發(fā)平臺(tái)
    的頭像 發(fā)表于 07-19 09:04 ?6040次閱讀
    基于<b class='flag-5'>睿</b><b class='flag-5'>擎</b><b class='flag-5'>派</b>輕松玩轉(zhuǎn)<b class='flag-5'>CANopen</b>電機(jī)控制

    基于輕松玩轉(zhuǎn)Modbus工業(yè)通信

    。今天,我們就帶來一篇實(shí)戰(zhàn)教程,教大家如何基于/工業(yè)平臺(tái),分別作為ModbusRTU主機(jī)和ModbusTCP主機(jī),讀取Modbus
    的頭像 發(fā)表于 07-23 17:05 ?3939次閱讀
    基于<b class='flag-5'>睿</b><b class='flag-5'>擎</b><b class='flag-5'>派</b>輕松玩轉(zhuǎn)Modbus工業(yè)通信

    】EtherCAT總線IO模塊讀寫

    在上一篇文章《【CANOpen總線IO
    的頭像 發(fā)表于 12-31 19:07 ?5886次閱讀
    【<b class='flag-5'>睿</b><b class='flag-5'>擎</b><b class='flag-5'>派</b>】EtherCAT<b class='flag-5'>總線</b><b class='flag-5'>之</b><b class='flag-5'>IO</b><b class='flag-5'>模塊</b><b class='flag-5'>讀寫</b>

    3562快速上手體驗(yàn)

    1引言隨著物聯(lián)網(wǎng)和工業(yè)自動(dòng)化的快速發(fā)展,嵌入式開發(fā)板的需求日益增長。3562作為一款基于瑞芯微RK3562處理器的高性能開發(fā)板,憑借其強(qiáng)大的處理能力和豐富的外設(shè)接口,成為了嵌入式開發(fā)者的新選擇
    的頭像 發(fā)表于 03-04 21:19 ?6834次閱讀
    <b class='flag-5'>睿</b><b class='flag-5'>擎</b><b class='flag-5'>派</b>3562快速上手體驗(yàn)

    Canopen協(xié)議讀后感想

    ,那么不僅要實(shí)現(xiàn)CANopen的CiA DS301協(xié)議,而且還需要實(shí)現(xiàn)符合開發(fā)模塊需求的子協(xié)議規(guī)范,例如CiA
    發(fā)表于 09-21 12:58

    XGate-COP10 CANopen協(xié)議轉(zhuǎn)換模塊硬件設(shè)計(jì)指

    XGate-COP10是一款CANopen從站協(xié)議轉(zhuǎn)換模塊,其內(nèi)部已經(jīng)集成了CANopen從站協(xié)議棧代碼,不需要進(jìn)行二次開發(fā)。
    發(fā)表于 03-06 14:54 ?19次下載

    CANopen協(xié)議講座(1)CAN總線簡介

    CANopen協(xié)議講座(1)CAN總線簡介 CANopen協(xié)議以其成熟的結(jié)構(gòu)、抗干擾能力強(qiáng)等
    發(fā)表于 03-26 17:27 ?81次下載

    CANopen協(xié)議講座(5)CANopen從站模塊(XGa

    CANopen協(xié)議講座(5)CANopen從站模塊(XGate-COP10) CANopen
    發(fā)表于 03-26 17:38 ?82次下載

    CANopen協(xié)議講座(6)CANopen從站模塊(Tin

    CANopen協(xié)議講座(6)CANopen從站模塊(TinyARM) 隨著國內(nèi)電力事業(yè)前所未有的發(fā)展,電力資源的需求也迅速增長。為保證電
    發(fā)表于 03-26 17:40 ?106次下載

    CAN總線轉(zhuǎn)CANopen方案推薦

    廣成科技GCAN-30X系列模塊是一系列定制型的CANopen轉(zhuǎn)換模塊,該模塊是在CAN總線網(wǎng)關(guān)轉(zhuǎn)換器設(shè)備的基礎(chǔ)上在CAN
    的頭像 發(fā)表于 03-02 11:06 ?9370次閱讀
    CAN<b class='flag-5'>總線</b>轉(zhuǎn)<b class='flag-5'>CANopen</b>方案推薦

    IO耦合器如何通過CANopen總線進(jìn)行通訊

    can io模塊一般指的是集成有CAN總線接口,可以通過CANopen總線進(jìn)行通訊的IO耦合器。
    的頭像 發(fā)表于 04-22 17:23 ?3558次閱讀

    CANopen IO耦合器功能的實(shí)現(xiàn)

    canopen分布式io是集成有CANBUS接口的IO耦合器,它可以通過CANopen總線與支持CANo
    的頭像 發(fā)表于 10-26 16:50 ?1911次閱讀

    虹科推出多款CANopen IO模塊及hipecs系列模塊通訊測試

    /Positive Switching,與總線和系統(tǒng)供電隔離,所有輸出端具有短路保護(hù)的特性,支持DS301和DS401,CAN端支持常用波特率,高達(dá)1Mbit/s,歡迎聯(lián)系虹科選購。
    的頭像 發(fā)表于 11-25 10:53 ?1924次閱讀

    淺談CANopen協(xié)議虹科CANopen IO方案

    01CANopen概述CANopen是一種架構(gòu)在CAN串行總線系統(tǒng)上的高層通訊協(xié)議,也是一種針對于行業(yè)的標(biāo)準(zhǔn)化的協(xié)議。該
    的頭像 發(fā)表于 11-19 16:11 ?2055次閱讀
    淺談<b class='flag-5'>CANopen</b><b class='flag-5'>協(xié)議</b><b class='flag-5'>之</b>虹科<b class='flag-5'>CANopen</b> <b class='flag-5'>IO</b>方案

    基于輕松玩轉(zhuǎn)EtherCAT主站,實(shí)現(xiàn)電機(jī)精確控制

    總線技術(shù)。本次實(shí)戰(zhàn)教程將基于平臺(tái),演示實(shí)現(xiàn):EtherCAT主站開發(fā)CSP模式伺服電機(jī)精準(zhǔn)控制遠(yuǎn)程IO流水燈聯(lián)動(dòng)開啟工業(yè)實(shí)時(shí)通信開發(fā)新
    的頭像 發(fā)表于 07-30 17:03 ?5404次閱讀
    基于<b class='flag-5'>睿</b><b class='flag-5'>擎</b><b class='flag-5'>派</b>輕松玩轉(zhuǎn)EtherCAT主站,實(shí)現(xiàn)電機(jī)精確控制
    辽阳市| 伊金霍洛旗| 南宫市| 同江市| 长治县| 吉隆县| 团风县| 昌黎县| 中方县| 扎兰屯市| 巧家县| 信宜市| 乐亭县| 霍邱县| 天柱县| 通州区| 即墨市| 丘北县| 扬州市| 东源县| 乌苏市| 如东县| 许昌县| 天气| 武城县| 陕西省| 辛集市| 福州市| 北海市| 苗栗县| 太仆寺旗| 保靖县| 洛扎县| 乡宁县| 盖州市| 莆田市| 闽侯县| 三门县| 仪征市| 监利县| 亳州市|