?? modbus_rtu.c
字號:
//****************************************************************************
//Copyright (c) 2007-2008 ABX CO,.LTD
//----------All rights reserved----------
//文件名稱: modbusrtu.c
//模塊功能: MODBUSRTU通訊協議
//創建日期: 2008.01.2
//創 建 人: 羅德良
//參考文檔: LPC2104開發板
//說 明: 參照原modbusrtu.c修改成平臺無關性
//修改歷史:
//****************************************************************************
#define IN_MODBUS_RTU
#include "config.h"
//寄存器在此定義
//內部寄存器定義
#define AICOUNT 35 //AI路數
#define AOCOUNT 146 //AO路數
#define DOCOUNT 8 //DO路數
#define DICOUNT 8 //DI路數
/******************************************
ui16AiReg[0]-[15] AI量化值
ui16AiReg[16] 內部溫度值
ui16AiReg[17]-[32] AI采樣值
設備信息
ui16AiReg[33] 設備類型
ui16AiReg[34] 設備版本號
ui16AoReg[0]-[1] AO
ui16AoReg[2]-[17] DI計數值(兩寄存器為一路)
以下為配置參數
ui16AoReg[18] 存盤請求寄存器
ui16AoReg[19] 站號
ui16AoReg[20] Uart0波特率
ui16AoReg[21] Uart0數據位(Bit7), 校驗位(Bit6,5), 停止位(Bit4)
ui16AoReg[22] Uart0幀間隔時間
ui16AoReg[23] Uart1波特率
ui16AoReg[24] Uart1數據位(Bit7), 校驗位(Bit6,5), 停止位(Bit4)
ui16AoReg[25] Uart1幀間隔時間
ui16AoReg[26]-[27] AO零位
ui16AoReg[28]-[29] AO滿度
ui16AoReg[30]-[37] AI零位(I)
ui16AoReg[38]-[45] AI滿度(I)
ui16AoReg[46]-[53] AI零位(V)
ui16AoReg[54]-[61] AI滿度(V)
ui16AoReg[62]-[69] AI顯示量程下限
ui16AoReg[70]-[77] AI顯示量程上限
ui16AoReg[78]-[85] AI顯示小數位數
ui16AoReg[86]-[93] AI報警上限
ui16AoReg[94]-[101] AI報警下限
ui16AoReg[102] 內部溫度報警上限
ui16AoReg[103] 內部溫度報警下限
ui16AoReg[104]-[111]AI信號類型
ui16AoReg[112]-[119]DI工作模式
ui16AoReg[120]-[127]DO工作模式
ui16AoReg[128]-[135]DO控制源
ui16AoReg[136]-[143]DO點動延時寄存器
ui16AoReg[144]-[145]AO輸出寄存器
******************************************/
volatile UINT16 ui16AiReg[AICOUNT]; //AI寄存器
volatile UINT16 ui16AoReg[AOCOUNT]; //AO寄存器
volatile UCHAR ucDoReg[DOCOUNT / 8]; //DO寄存器
volatile UCHAR ucDiReg[DICOUNT / 8]; //DI寄存器
//協議結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucMess[256]; //內容
}tagMODBUSREV; //MODBUS接收數據結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucStarAdrHi; //起始寄存器地址高字節
UCHAR ucStarAdrLo; //起始寄存器地址低字節
UCHAR ucCntHi; //數量高字節
UCHAR ucCntLo; //數量低字節
UCHAR ucCrcHi; //CRC高字節
UCHAR ucCrcLo; //CRC低字節
}tagMODREAD; //MODBUS讀數據結構及多寫應答結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucByteCnt; //字節數
UCHAR ucMess[256]; //內容
}tagMODREADRESP; //MODBUS讀應答數據結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucAdrHi; //寄存器地址高字節
UCHAR ucAdrLo; //寄存器地址低字節
UCHAR ucDatHi; //數據高字節
UCHAR ucDatLo; //數據低字節
UCHAR ucCrcHi; //CRC高字節
UCHAR ucCrcLo; //CRC低字節
}tagWRSINGAL; //MODBUS寫單個寄存器及應答結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucStarAdrHi; //起始寄存器地址高字節
UCHAR ucStarAdrLo; //超始寄存器地址低字節
UCHAR ucCntHi; //數量高字節
UCHAR ucCntLo; //數量低字節
UCHAR ucByteCnt; //字節數
UCHAR ucMess[64]; //內容
}tagWRMULTE; //MODBUS寫多個寄存器數據結構
typedef struct
{
UCHAR ucSta; //站號
UCHAR ucFun; //功能碼
UCHAR ucLen; //長度
UCHAR ucFunNo; //代號
UCHAR ucMess[128]; //內容
}tagWRCONFIG; //配置結構
//MODBUS異常碼
#define NO_ERR 0x00 //無異常
#define FUN_ERR 0x01 //不支持的功能碼
#define ADR_ERR 0x02 //地址超出范圍
#define VAL_ERR 0x03 //數據超出范圍
#define FAIL_ERR 0x04 //執行失敗
#define CALL_ERR 0x05 //調用參數錯誤
//****************************************************************************
//函數名稱: Read_MultAI
//函數功能: 讀輸入寄存器(AI)
//輸入參數: UCHAR *ucpRevcBuff 接收緩沖
// UCHAR *ucpSendBuff 發送緩沖
// UCHAR *ucpLen 發送緩沖長度
//輸出參數: void
//返 回 值: UCHAR 異常碼
//創建日期: 2008.01.02
//創 建 人: 羅德良
//參考文檔:
//說 明: Modbus 4號功能碼
//修改歷史:
//****************************************************************************
UCHAR Read_MultAI(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, i, ui16Len;
UCHAR m;
tagMODREAD *tagpModRead;
tagMODREADRESP *tagpModReadResp;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpModRead = (tagMODREAD *)ucpRevcBuff; //接收緩沖區
tagpModReadResp = (tagMODREADRESP *)ucpSendBuff; //應答緩沖區
tagpModReadResp -> ucSta = tagpModRead -> ucSta; //站號
tagpModReadResp -> ucFun = tagpModRead -> ucFun; //功能碼
//寄存器起始地址
ui16Temp = tagpModRead -> ucStarAdrHi * 256ul + tagpModRead -> ucStarAdrLo;
if (ui16Temp >= AICOUNT) return (ADR_ERR); //寄存器超出范圍
//寄存器數量
ui16Len = tagpModRead -> ucCntHi * 256ul + tagpModRead -> ucCntLo;
if ((ui16Len + ui16Temp) > AICOUNT) return(ADR_ERR); //寄存器超出范圍
//返回數據字節數
tagpModReadResp -> ucByteCnt = ui16Len * 2;
//內容處理
m = 0;
for (i = ui16Temp; i < ui16Len + ui16Temp; i++)
{
tagpModReadResp -> ucMess[m++] = ui16AiReg[i] / 256ul;
tagpModReadResp -> ucMess[m++] = ui16AiReg[i];
}
//計算CRC
ui16Temp = CRC16((UCHAR *)tagpModReadResp, 3 + tagpModReadResp -> ucByteCnt);
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt] = ui16Temp / 256;
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt + 1] = ui16Temp;
//發送緩沖長度
*ucpLen = 3 + tagpModReadResp -> ucByteCnt + 2;
return (NO_ERR);
}
//****************************************************************************
//函數名稱: Read_MultAO
//函數功能: 讀保持寄存器(AO)
//輸入參數: UCHAR *ucpRevcBuff 接收緩沖
// UCHAR *ucpSendBuff 發送緩沖
// UCHAR *ucpLen 發送緩沖長度
//輸出參數: void
//返 回 值: UCHAR 異常碼
//創建日期: 2008.01.02
//創 建 人: 羅德良
//參考文檔:
//說 明: Modbus 3號功能碼
//修改歷史:
//****************************************************************************
UCHAR Read_MultAO(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, i, ui16Len;
UCHAR m;
tagMODREAD *tagpModRead;
tagMODREADRESP *tagpModReadResp;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpModRead = (tagMODREAD *)ucpRevcBuff; //接收緩沖區
tagpModReadResp = (tagMODREADRESP *)ucpSendBuff; //應答緩沖區
tagpModReadResp -> ucSta = tagpModRead -> ucSta; //站號
tagpModReadResp -> ucFun = tagpModRead -> ucFun; //功能碼
//寄存器起始地址
ui16Temp = tagpModRead -> ucStarAdrHi * 256ul + tagpModRead -> ucStarAdrLo;
if (ui16Temp >= AOCOUNT) return (ADR_ERR); //寄存器超出范圍
//寄存器數量
ui16Len = tagpModRead -> ucCntHi * 256ul + tagpModRead -> ucCntLo;
if ((ui16Len + ui16Temp) > AOCOUNT) return(ADR_ERR); //寄存器超出范圍
//返回數據字節數
tagpModReadResp -> ucByteCnt = ui16Len * 2;
//內容處理
m = 0;
for (i = ui16Temp; i < ui16Len + ui16Temp; i++)
{
tagpModReadResp -> ucMess[m++] = ui16AoReg[i] / 256ul;
tagpModReadResp -> ucMess[m++] = ui16AoReg[i];
}
//計算CRC
ui16Temp = CRC16((UCHAR *)tagpModReadResp, 3 + tagpModReadResp -> ucByteCnt);
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt] = ui16Temp / 256;
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt + 1] = ui16Temp;
//發送緩沖長度
*ucpLen = 3 + tagpModReadResp -> ucByteCnt + 2;
return (NO_ERR);
}
//****************************************************************************
//函數名稱: Read_MultCoil
//函數功能: 讀取線圈狀態
//輸入參數: UCHAR *ucpRevcBuff 接收緩沖
// UCHAR *ucpSendBuff 發送緩沖
// UCHAR *ucpLen 發送緩沖長度
//輸出參數: void
//返 回 值: UCHAR 異常碼
//創建日期: 2008.01.02
//創 建 人: 羅德良
//參考文檔:
//說 明: Modbus 1號功能碼
//修改歷史:
//****************************************************************************
UCHAR Read_MultCoil(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, i, ui16Len;
UCHAR ucTemp, ucByteNo, ucBitNo;
tagMODREAD *tagpModRead;
tagMODREADRESP *tagpModReadResp;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpModRead = (tagMODREAD *)ucpRevcBuff; //接收緩沖區
tagpModReadResp = (tagMODREADRESP *)ucpSendBuff; //應答緩沖區
tagpModReadResp -> ucSta = tagpModRead -> ucSta; //站號
tagpModReadResp -> ucFun = tagpModRead -> ucFun; //功能碼
//寄存器起始地址
ui16Temp = tagpModRead -> ucStarAdrHi * 256ul + tagpModRead -> ucStarAdrLo;
if (ui16Temp >= DOCOUNT) return (ADR_ERR); //寄存器超出范圍
//寄存器數量
ui16Len = tagpModRead -> ucCntHi * 256ul + tagpModRead -> ucCntLo;
if ((ui16Len + ui16Temp) > DOCOUNT) return(ADR_ERR); //寄存器超出范圍
//返回數據字節數
tagpModReadResp -> ucByteCnt = ui16Len / 8;
if ((ui16Len % 8) != 0)
{
tagpModReadResp -> ucByteCnt += 1;
}
//內容處理
i = 0;
while (i < ui16Len)
{
//取寄存器位值
ucByteNo = ui16Temp / 8;
ucBitNo = ui16Temp % 8;
ucTemp = ((ucDoReg[ucByteNo] >> ucBitNo) & 0x01);
if ((i % 8) == 0)
{
tagpModReadResp -> ucMess[i / 8] = 0x00;
}
//填充到發送緩沖
tagpModReadResp -> ucMess[i / 8] |= (ucTemp << (i % 8));
i++;
ui16Temp++;
}
//計算CRC
ui16Temp = CRC16((UCHAR *)tagpModReadResp, 3 + tagpModReadResp -> ucByteCnt);
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt] = ui16Temp / 256;
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt + 1] = ui16Temp;
//發送緩沖長度
*ucpLen = 3 + tagpModReadResp -> ucByteCnt + 2;
return (NO_ERR);
}
//****************************************************************************
//函數名稱: Read_MultDI
//函數功能: 讀取離輸入狀態
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -