📄 uartwaitfunc.c
字号:
return result;
}
/*******************************************************************************
函数名: SingleFrameWriteByteWait
描 述: 单帧写字节函数,执行该函数后将数据写入指定字节地址
输 入: byAddr 选用的下位机地址,如1,2等
pabyByteInput 存放写入数据的首地址,该参数应传递数据格式的参数
pszDecTag 写字节的信息TAG,详见通讯协议的方式
dwSize 写字节的个数
输 出: 无
返回值: 写入正确返回发送字节数,包括帧头和结尾符,否则表示执行的错误代码,
*******************************************************************************/
static SingleFrameWriteByteWait(INT8U byAddr, const INT8U *pabyByteInput, const INT8S *pszDecTag, INT32U dwSize)
{
STC_TAG_COMMAND stcTagCmd; //定义操作变量stcTagCmd
INT32S result = ECOM_NOERROR; //错误返回值
INT32S iSendByteNum; //实际发送字节数
INT32S iRecvTagLen = 0; //返回桢的字节数
/**********************************************************
pszRecv指向接收到的桢数据, 开辟12字节空间
**********************************************************/
INT8U* pszRecv = (INT8U *)malloc(12);
/**********************************************************
检验传入参数的正确性,dwSize乘2是因为发送的字节数据,加17是
因为桢长还要包括前缀和后缀的长度,及tag的6字节
**********************************************************/
if ((pabyByteInput == NULL) || (dwSize * 2 + 17 > g_iMaxFrameSize))
{
result = ECOM_BADPARA; //检验传入参数的正确性;
goto SingleWriteByteError; //错误返回
}
if (!IsDecodeSuccess(pszDecTag, &(stcTagCmd.stcTag), TAG_COMMAND_WRITE))
{
result = ECOM_BADPARA; //判断TAG是否有效,有效解码至stcTagCmd.stcTag;
goto SingleWriteByteError;
}
if (ECOM_NOERROR == result) //如果参数无错,则发送数据桢;发送正确返回发送字节数
{
stcTagCmd.byRange = dwSize;
iSendByteNum = SendWriteByteCommand(&stcTagCmd, byAddr, pabyByteInput);
}
if (iSendByteNum >= 0) //数据桢发送正确,则接收数据桢
{
#ifndef FORTESTONLY //测试编译开关
iRecvTagLen = GetModbusFrame(pszRecv);
#else
extern INT8U testbuf[50];
extern INT32S testsize;
iRecvTagLen = testsize;
pszRecv = testbuf;
#endif
}
else
{
result = iSendByteNum; //发送不正确,错误代码给result
goto SingleWriteByteError;
}
if (iRecvTagLen < 0)
{
result = iRecvTagLen; //接收不正确,错误代码给result
goto SingleWriteByteError;
}
else //数据桢接收正确,则进行校验
{
result = ModbusFrameCheck(pszRecv, iRecvTagLen, byAddr, COMMAND_CHAR_WR, dwSize);
}
if (ECOM_NOERROR == result) //校验正确,
{
free(pszRecv); //释放开辟的资源
return iSendByteNum;
}
else
{
goto SingleWriteByteError;
}
SingleWriteByteError:
free(pszRecv); //释放开辟的资源
return result;
}
/*******************************************************************************
写字节通讯帧, 协议为MODBUS协议ASCII方式
协议组成(':' + 设备地址 + 功能代码(0x04) + 字节TAG地址 + 写入字节数 + 写入值
+ LRC校验 + 结束符)
EXAMPLE: 设备地址 = 22(DEC), TAG = MB14(DEC),写入连续4个字节, 写入值为十六进制
{0x12, 0x31, 0x33, 0xA5}, 若通讯错误,设错误代码为15(DEC)
发送帧
帧头 设备地址 功能代码 TAG MB14(DEC) = MB000E(HEX) 写入字节数
字节 _1__ ____2____ ____2____ ______________6______________ ____2____
HEX 0x3A 0x31 0x36 0x30 0x34 0x4E 0x42 0x30 0x30 0x30 0x45 0x30 0x34
ASC ':' '1' '6' '0' '4' 'M' 'B' '0' '0' '0' 'E' '0' '4'
写入值(占用字节数为写入字节数 * 2) LRC校验 结束符
__________________8____________________ ____2____ ____2____
HEX 0x31 0x32 0x33 0x31 0x33 0x33 0x41 0x35 0x^^ 0x^^ 0x0D 0x0A
ASC '1' '2' '3' '1' '3' '3' 'A' '5' '^' '^' '\r' '\n'
正常返回帧
帧头 设备地址 功能代码 LRC校验 结束符
字节 _1__ ____2____ ____2____ ____2____ ____2____
HEX 0x3A 0x31 0x36 0x30 0x34 0x^^ 0x^^ 0x0D 0x0A
ASC ':' '1' '6' '0' '4' '^' '^' '\r' '\n'
错误返回帧
帧头 设备地址 功能代码 错误代码 LRC校验 结束符
字节 _1__ ____2____ ____2____ ____2____ ____2____ ____2____
HEX 0x3A 0x31 0x36 0x38 0x34 0x30 0x46 0x^^ 0x^^ 0x0D 0x0A
ASC ':' '1' '6' '8' '4' '0' 'F' '^' '^' '\r' '\n'
注意:0x^^代表实际运算的校验和, '^'表示对应的校验和的ASCII表达方式
*******************************************************************************/
/*******************************************************************************
函数名: COM_WriteByteWait
描 述: 写字节等待函数,执行该函数后将数据写入指定字节地址
输 入: byAddr 选用的下位机地址,如1,2等
pabyByteInput 存放写入数据的首地址,参数以16进制格式输入,如0x12,0xAB
pszDecTag 写字节的信息TAG,如MB18,详见通讯协议的方式
dwSize 写字节的个数
输 出: 无
返回值: 写入正确返回ECOM_NOERROR,否则表示执行的错误代码,
*******************************************************************************/
INT32S WINAPI COM_WriteByteWait(INT8U byAddr, const INT8U *pabyByteInput,const INT8S *pszDecTag, INT32U dwSize)
{
INT32S result = ECOM_NOERROR; //错误返回值
INT32S iSendByteNum = 0; //实际发送字节数
INT32U dwWriteNum = 1; //要写的次数
INT32U dwWriteNumBak;
INT32U dwSingleWriteSize;
INT32S startadd;
BOOL MultWrite = FALSE;
/*存操作的tag,以便修改*/
INT8S *DecTagBak = (INT8S *)malloc(10);
sscanf(pszDecTag + 2, "%d", &startadd);
sprintf(DecTagBak,"%C%C%01d",*pszDecTag, *(pszDecTag + 1), startadd);
/**********************************************************
检验传入参数的正确性
**********************************************************/
if (pabyByteInput == NULL)
{
result = ECOM_BADPARA; //检验传入参数的正确性;
goto WriteByteError; //错误返回
}
if (g_iMaxFrameSize - 17 < 2) //帧过小,不能完成单帧发送一个字节
{
result = ECOM_TOOSMALLSIZE;
goto WriteByteError;
}
if (dwSize * 2 + 17 > g_iMaxFrameSize) //多帧写
{
MultWrite = TRUE;
if (dwSize % ((g_iMaxFrameSize - 17) / 2))
dwWriteNum = dwSize / ((g_iMaxFrameSize - 17) / 2) + 1;
else
dwWriteNum = dwSize / ((g_iMaxFrameSize - 17) / 2);
}
dwWriteNumBak = dwWriteNum;
while (dwWriteNum != 0)
{
/*确定每帧写的个数*/
if (MultWrite)
{
if (dwWriteNum > 1) //多帧写
{
dwSingleWriteSize = (g_iMaxFrameSize - 17) / 2;
}
else //最后一次发写命令
{
dwSingleWriteSize = dwSize - (dwWriteNumBak - 1) * ((g_iMaxFrameSize - 17) / 2);
}
}
else //单帧写
{
dwSingleWriteSize = dwSize;
}
/*调用单帧写函数*/
result = SingleFrameWriteByteWait(byAddr, pabyByteInput + iSendByteNum, DecTagBak, dwSingleWriteSize);
iSendByteNum = iSendByteNum + ((result - 17) / 2);
if (result > 0) //写正确,
{
if (MultWrite)
{
if (dwWriteNum > 1) //调用TagChange()函数,更改TAG地址
{
result = TagChange(DecTagBak, COMMAND_CHAR_WR);
if (result == 0)
{
result = ECOM_BADPARA;
goto WriteByteError;
}
}
}
dwWriteNum--;
result = ECOM_NOERROR;
}
else
{
goto WriteByteError;
}
} //写字节结束
free(DecTagBak); //释放开辟的资源
return ECOM_NOERROR;
WriteByteError:
free(DecTagBak); //释放开辟的资源
return result;
}
/*******************************************************************************
函数名: SingleFrameWriteWordWait
描 述: 单帧写字函数,执行该函数后将数据写入指定字地址
输 入: byAddr 选用的下位机地址,如1,2等
pawWordInput 存放写入数据的首地址,该参数应传递数据格式的参数
pszDecTag 写字的信息TAG,详见通讯协议的方式
dwSize 写字的个数
输 出: 无
返回值: 写入正确返回发送字节数,包括帧头和结束符,否则表示执行的错误代码,
*******************************************************************************/
static SingleFrameWriteWordWait(INT8U byAddr, const INT16U *pawWordInput, const INT8S *pszDecTag, INT32U dwSize)
{
STC_TAG_COMMAND stcTagCmd; //定义操作变量stcTagCmd
INT32S result = ECOM_NOERROR; //错误返回值
INT32S iSendWordNum; //实际发送字数
INT32S iRecvTagLen = 0; //返回桢的字节数
/**********************************************************
pszRecv指向接收到的桢数据, 开辟12字节空间
**********************************************************/
INT8U* pszRecv = (INT8U *)malloc(12);
/**********************************************************
检验传入参数的正确性,dwSize乘4是因为发送的字数据,加17是
因为桢长还要包括前缀和后缀的长度,及tag的6字节
**********************************************************/
if ((pawWordInput == NULL) || (dwSize * 4 + 17 > g_iMaxFrameSize))
{
result = ECOM_BADPARA; //检验传入参数的正确性;
goto SingleWriteWordError; //错误返回
}
if (!IsDecodeSuccess(pszDecTag, &(stcTagCmd.stcTag), TAG_COMMAND_WRITE))
{
result = ECOM_BADPARA; //判断TAG是否有效,有效解码至stcTagCmd.stcTag;
goto SingleWriteWordError;
}
if (ECOM_NOERROR == result) //如果参数无错,则发送数据桢;发送正确返回发送字节数
{
stcTagCmd.byRange = dwSize;
iSendWordNum = SendWriteWordCommand(&stcTagCmd, byAddr, pawWordInput);
}
if (iSendWordNum >= 0) //数据桢发送正确,则接收数据桢
{
#ifndef FORTESTONLY //测试编译开关
iRecvTagLen = GetModbusFrame(pszRecv);
#else
extern INT8U testbuf[50];
extern INT32S testsize;
iRecvTagLen = testsize;
pszRecv = testbuf;
#endif
}
else
{
result = iSendWordNum; //发送不正确,错误代码给result
goto SingleWriteWordError;
}
if (iRecvTagLen < 0)
{
result = iRecvTagLen; //接收不正确,错误代码给result
goto SingleWriteWordError;
}
else //数据桢接收正确,则进行校验
{
result = ModbusFrameCheck(pszRecv, iRecvTagLen, byAddr, COMMAND_SHORT_WR, dwSize);
}
if (ECOM_NOERROR == result) //校验正确,
{
free(pszRecv); //释放开辟的资源
return iSendWordNum;
}
else
{
goto SingleWriteWordError;
}
SingleWriteWordError:
free(pszRecv); //释放开辟的资源
return result;
}
/*******************************************************************************
写字通讯帧, 协议为MODBUS协议ASCII方式
协议组成(':' + 设备地址 + 功能代码(0x06) + 字TAG地址 + 写入字数 + 写入值
+ LRC校验 + 结束符)
EXAMPLE: 设备地址 = 22(DEC), TAG = MW14(DEC),写入连续2个字, 写入值为十六进制
{0x1231, 0x33A5}, 若通讯错误,设错误代码为15(DEC)
发送帧
帧头 设备地址 功能代码 TAG MW14(DEC) = MW000E(HEX) 写入字数
字节 _1__ ____2____ ____2____ ______________6______________ ____2____
HEX 0x3A 0x31 0x36 0x30 0x36 0x4E 0x57 0x30 0x30 0x30 0x45 0x30 0x32
ASC ':' '1' '6' '0' '6' 'M' 'W' '0' '0' '0' 'E' '0' '2'
写入值(占用字节数 = 写入字数 * 4 ) LRC校验 结束符
__________________8____________________
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -