专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
Modbus主机如何采集Modbus从机所测得的数据
2019-10-16 00:35
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
8165
23
1710
我现在是 Modbus从机可以准确的采集SHT10的温湿度,MQ-2气体,和光照指标 上位机用 Modbus Poll显示。
现在想 用另一个单片机 采集到从机的这些环境指标 发送至串口助手 怎么办?
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
23条回答
song15032
2019-10-16 08:25
yklstudent 发表于 2016-7-19 13:19
你要做的就是做个MODBUS协议主机,周期读取MODBUS协议从机的内容;
是啊,可是主机的Modbus协议怎么读取呢。 这是我从机部分 Modbus内容:
[mw_shl_code=c,true]/*******************************串口发送函数 ********************************/
void Begin_send(void)
{
DE_OUT; //处于发送
uartsends(sendBuf,sendCount);
DE_IN; //发送完后将485置于接收状态
receCount = 0; //清接收地址偏移寄存器
}
//fuction:01 读单个或多个线圈状态
void readCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint position;
uint i,k;
uint tempData;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
position = k + 3;
sendBuf[position] = 0;
for(i=0;i<8;i++)
{
getCoilVal(tempAddr,&tempData);
sendBuf[position] |= tempData << i;
tempAddr++;
if(tempAddr >= addr+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 0x01;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff;
byteCount++;
sendBuf[byteCount] = crcData >> 8;
sendCount = byteCount + 1;
Begin_send();
}
//fuction:02 读取线圈输入(只读寄存器)状态
void readInPutCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint position;
uint i,k;
uint tempData;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr +10000; //只读线圈寄存器偏移地址10000
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
position = k + 3;
sendBuf[position] = 0;
for(i=0;i<8;i++)
{
getCoilVal(tempAddr,&tempData);
sendBuf[position] |= tempData << i;
tempAddr++;
if(tempAddr >= addr+10000+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 0x02;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff;
byteCount++;
sendBuf[byteCount] = crcData >> 8;
sendCount = byteCount + 1;
Begin_send();
}
/********function code : 03,读取多个寄存器值 ********/
void readRegisters(void)
{
uint addr;
uint tempAddr;
uint crcData;
uint readCount;
uint byteCount;
uint i;
uint tempData = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+40000; //+40000,保持寄存器偏移地址
readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
byteCount = readCount * 2; //每个寄存器内容占高,低两个字节
for(i=0;i<byteCount;i+=2,tempAddr++)
{
getRegisterVal(tempAddr,&tempData);
sendBuf[i+3] = tempData >> 8;
sendBuf[i+4] = tempData & 0xff;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 3; //function code : 03
sendBuf[2] = byteCount;
byteCount += 3; //加上前面的地址,功能码,地址 共3+byteCount个字节
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff; // CRC代码低位在前
byteCount++;
sendBuf[byteCount] = crcData >> 8 ; //高位在后
sendCount = byteCount + 1; //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
Begin_send();
}
//fuction 04:读取输入寄存器
void readInPutRegisters(void)
{
uint addr;
uint tempAddr;
uint crcData;
uint readCount;
uint byteCount;
uint i;
uint tempData = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+30000; //+输入寄存器偏移地址:30000
readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
byteCount = readCount * 2; //每个寄存器内容占高,低两个字节
for(i=0;i<byteCount;i+=2,tempAddr++)
{
getRegisterVal(tempAddr,&tempData);
sendBuf[i+3] = tempData >> 8;
sendBuf[i+4] = tempData & 0xff;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 4; //function code : 04
sendBuf[2] = byteCount;
byteCount += 3; //加上前面的地址,功能码,地址 共3+byteCount个字节
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff; // CRC代码低位在前
byteCount++;
sendBuf[byteCount] = crcData >> 8 ; //高位在后
sendCount = byteCount + 1; //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
Begin_send();
}
//fuction:05 ,强制单个线圈
void forceSingleCoil(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint onOff;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
onOff = (receBuf[4]<<8) + receBuf[5];
if(onOff == 0xff00)
{
tempData = 1;//设为ON
}
else if(onOff == 0x0000)//设为OFF
{
tempData = 0;
}
setCoilVal(tempAddr,tempData);
for(i=0;i<receCount;i++)
{
sendBuf
= receBuf
;
}
sendCount = receCount;
Begin_send();
}
/****************fuction:06设置单个寄存器ok**********************************************************/
//主机器发送 地址,功能码,寄存器高位,寄存器低位,数据数高位, 数数低位,CRC低位,CRC高位
//例如设置D0 发送, 01 06 00 3F 00 01 */
/*********************************************************************************/
void presetSingleRegister(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint crcData;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = (addr+40000);
tempData = (receBuf[4]<<8) + receBuf[5];
setRegisterVal(tempAddr,tempData);
sendBuf[0] = LocalAddr;
sendBuf[1] = 6; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] =receBuf[4];
sendBuf[5] =receBuf[5];
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/********从机响应主机问询函数,function code : 15,强置多线圈值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1] receBuf[2] receBuf[3] receBuf[4] receBuf[5] receBuf[6] receBuf[7] receBuf[8] ... receBuf[9] receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码, 起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数, 数据高位, 数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void forceMultipleCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint tempData;
uint i,k;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5];
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
for(i=0;i<8;i++)
{
tempData = (receBuf[k+3] >>i)&0x01;
setCoilVal(tempAddr,tempData);
tempAddr++;
if(tempAddr >= addr+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 15; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = bitCount >> 8;//待设置寄存器数量高位
sendBuf[5] = bitCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/********从机响应主机问询函数,function code : 16,设置多个寄存器值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1] receBuf[2] receBuf[3] receBuf[4] receBuf[5] receBuf[6] receBuf[7] receBuf[8] ... receBuf[9] receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码, 起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数, 数据高位, 数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void presetMultipleRegisters(void)
{
uint addr;
uint tempAddr;
uint setCount;
uint crcData;
uint tempData;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+40000;
setCount = (receBuf[4]<<8) + receBuf[5];
for(i=0;i<setCount;i++,tempAddr++)
{
tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];//待设置寄存器值
setRegisterVal(tempAddr,tempData);
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 16; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = setCount >> 8;//待设置寄存器数量高位
sendBuf[5] = setCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/*************************查询uart接收的数据包内容函数 **************************/
////函数功能:丛机根据串口接收到的数据包receBuf[1]里面的内容,即function code执行相应的命令
/********************************************************************************/
void checkComm0Modbus(void) //10ms内必须响应接收数据
{
uint crcData;
uint tempData;
uint temp;
if(receCount > 4) //如果接收到数据
{
switch(receBuf[1])
{
case 1: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 1)
{
readCoils(); //读取线圈输出状态(一个或多个)
}
receCount = 0;
}
}
break;
}
case 2: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 2)
{
readInPutCoils(); //读取线圈输入状态(一个或多个)
}
receCount = 0;
}
}
break;
}
case 3: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 3)
{
readRegisters(); //读取保持寄存器(一个或多个)
}
receCount = 0;
}
}
break;
}
case 4: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 4)
{
readInPutRegisters(); //读取输入寄存器(一个或多个)
}
receCount = 0;
}
}
break;
}
case 5: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 5)
{
forceSingleCoil(); //强置单个线圈 状态
}
receCount = 0;
}
}
break;
}
case 6: if(receCount >= 8)
{
if(receBuf[0]==LocalAddr)
{
crcData = crc16(receBuf,6);
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 6)
{
presetSingleRegister(); //预置单个保持寄存器
}
receCount = 0;
}
}
break;
case 15://设置多个线圈
tempData = receBuf[6];
tempData += 9; //数据个数
if(receCount >= tempData)
{
if(receBuf[0]==LocalAddr )
{
crcData = crc16(receBuf,tempData-2);
if(crcData == (receBuf[tempData-1]<<8)+ receBuf[tempData-2])//更改了??
{
forceMultipleCoils();
}
}
receCount = 0;
}
break;
case 16: //设置多个寄存器
{
tempData = (receBuf[4]<<8) + receBuf[5]; //设置寄存器个数
tempData = tempData * 2; //数据个数= 寄存器*2
tempData += 9; //从询问数据包格式可知,receCount应该等于9+byteCount
if(receCount >= tempData)
{
if(receBuf[0]==LocalAddr ) //核对地址
{
crcData = crc16(receBuf,tempData-2);
temp=receBuf[tempData-1];
temp=(temp<<8)+receBuf[tempData-2];
if(crcData == temp)
{
presetMultipleRegisters();
}
}
receCount = 0;
}
break;
}
default: break;
}
}
}
/********************以下为移植的数据修改区**************************************************/
//取线圈状态 返回0表示成功
uint getCoilVal(uint addr,uint *tempData)
{
uint tempAddr;
tempAddr = addr;//只取低8位地址
switch(tempAddr)
{
// case RWSTATUES0: *tempData = RWstatus0; break;
default: break;
}
return 0;
}
uint setCoilVal(uint addr,uint tempData)//设定线圈状态 返回0表示成功
{
uint tempAddr;
tempAddr = addr;
switch(tempAddr)
{
// case RWSTATUES0: RWstatus0= tempData; break;
default: break;
}
return 0;
}
/*******************************读取寄存器内容函数 返回0表示成功**************************/
uint getRegisterVal(uint addr,uint *tempData)
{
switch(addr)
{
case WEIDU: { *tempData =Temperature ; break; }
case SHIDU: { *tempData =Humidity ; break; }
case CO2: { *tempData =Co2 ; break; }
case RIZHAO: { *tempData =Rizhao ; break; }
default: break;
}
return 0;
}
/*******************************设置寄存器内容函数 *返回0表示成功*************************/
uint setRegisterVal(uint addr,uint tempData)
{
switch(addr)
{
case WEIDU: {Temperature=tempData ;break; }
case SHIDU: { Humidity=tempData ;break; }
case CO2: { Co2=tempData ;break; }
case RIZHAO: { Rizhao=tempData ; break; }
}
return 0;
}[/mw_shl_code]
加载中...
查看其它23个回答
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
是啊,可是主机的Modbus协议怎么读取呢。 这是我从机部分 Modbus内容:
[mw_shl_code=c,true]/*******************************串口发送函数 ********************************/
void Begin_send(void)
{
DE_OUT; //处于发送
uartsends(sendBuf,sendCount);
DE_IN; //发送完后将485置于接收状态
receCount = 0; //清接收地址偏移寄存器
}
//fuction:01 读单个或多个线圈状态
void readCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint position;
uint i,k;
uint tempData;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
position = k + 3;
sendBuf[position] = 0;
for(i=0;i<8;i++)
{
getCoilVal(tempAddr,&tempData);
sendBuf[position] |= tempData << i;
tempAddr++;
if(tempAddr >= addr+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 0x01;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff;
byteCount++;
sendBuf[byteCount] = crcData >> 8;
sendCount = byteCount + 1;
Begin_send();
}
//fuction:02 读取线圈输入(只读寄存器)状态
void readInPutCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint position;
uint i,k;
uint tempData;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr +10000; //只读线圈寄存器偏移地址10000
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
position = k + 3;
sendBuf[position] = 0;
for(i=0;i<8;i++)
{
getCoilVal(tempAddr,&tempData);
sendBuf[position] |= tempData << i;
tempAddr++;
if(tempAddr >= addr+10000+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 0x02;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff;
byteCount++;
sendBuf[byteCount] = crcData >> 8;
sendCount = byteCount + 1;
Begin_send();
}
/********function code : 03,读取多个寄存器值 ********/
void readRegisters(void)
{
uint addr;
uint tempAddr;
uint crcData;
uint readCount;
uint byteCount;
uint i;
uint tempData = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+40000; //+40000,保持寄存器偏移地址
readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
byteCount = readCount * 2; //每个寄存器内容占高,低两个字节
for(i=0;i<byteCount;i+=2,tempAddr++)
{
getRegisterVal(tempAddr,&tempData);
sendBuf[i+3] = tempData >> 8;
sendBuf[i+4] = tempData & 0xff;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 3; //function code : 03
sendBuf[2] = byteCount;
byteCount += 3; //加上前面的地址,功能码,地址 共3+byteCount个字节
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff; // CRC代码低位在前
byteCount++;
sendBuf[byteCount] = crcData >> 8 ; //高位在后
sendCount = byteCount + 1; //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
Begin_send();
}
//fuction 04:读取输入寄存器
void readInPutRegisters(void)
{
uint addr;
uint tempAddr;
uint crcData;
uint readCount;
uint byteCount;
uint i;
uint tempData = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+30000; //+输入寄存器偏移地址:30000
readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
byteCount = readCount * 2; //每个寄存器内容占高,低两个字节
for(i=0;i<byteCount;i+=2,tempAddr++)
{
getRegisterVal(tempAddr,&tempData);
sendBuf[i+3] = tempData >> 8;
sendBuf[i+4] = tempData & 0xff;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 4; //function code : 04
sendBuf[2] = byteCount;
byteCount += 3; //加上前面的地址,功能码,地址 共3+byteCount个字节
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff; // CRC代码低位在前
byteCount++;
sendBuf[byteCount] = crcData >> 8 ; //高位在后
sendCount = byteCount + 1; //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
Begin_send();
}
//fuction:05 ,强制单个线圈
void forceSingleCoil(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint onOff;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
onOff = (receBuf[4]<<8) + receBuf[5];
if(onOff == 0xff00)
{
tempData = 1;//设为ON
}
else if(onOff == 0x0000)//设为OFF
{
tempData = 0;
}
setCoilVal(tempAddr,tempData);
for(i=0;i<receCount;i++)
{
sendBuf = receBuf;
}
sendCount = receCount;
Begin_send();
}
/****************fuction:06设置单个寄存器ok**********************************************************/
//主机器发送 地址,功能码,寄存器高位,寄存器低位,数据数高位, 数数低位,CRC低位,CRC高位
//例如设置D0 发送, 01 06 00 3F 00 01 */
/*********************************************************************************/
void presetSingleRegister(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint crcData;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = (addr+40000);
tempData = (receBuf[4]<<8) + receBuf[5];
setRegisterVal(tempAddr,tempData);
sendBuf[0] = LocalAddr;
sendBuf[1] = 6; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] =receBuf[4];
sendBuf[5] =receBuf[5];
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/********从机响应主机问询函数,function code : 15,强置多线圈值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1] receBuf[2] receBuf[3] receBuf[4] receBuf[5] receBuf[6] receBuf[7] receBuf[8] ... receBuf[9] receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码, 起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数, 数据高位, 数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void forceMultipleCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint bitCount;
uint crcData;
uint tempData;
uint i,k;
uchar exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5];
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k<byteCount;k++)//字节位置
{
for(i=0;i<8;i++)
{
tempData = (receBuf[k+3] >>i)&0x01;
setCoilVal(tempAddr,tempData);
tempAddr++;
if(tempAddr >= addr+bitCount)//读完
{
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 15; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = bitCount >> 8;//待设置寄存器数量高位
sendBuf[5] = bitCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/********从机响应主机问询函数,function code : 16,设置多个寄存器值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1] receBuf[2] receBuf[3] receBuf[4] receBuf[5] receBuf[6] receBuf[7] receBuf[8] ... receBuf[9] receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码, 起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数, 数据高位, 数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void presetMultipleRegisters(void)
{
uint addr;
uint tempAddr;
uint setCount;
uint crcData;
uint tempData;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+40000;
setCount = (receBuf[4]<<8) + receBuf[5];
for(i=0;i<setCount;i++,tempAddr++)
{
tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];//待设置寄存器值
setRegisterVal(tempAddr,tempData);
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 16; //function code : 16
sendBuf[2] = addr >> 8; //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = setCount >> 8;//待设置寄存器数量高位
sendBuf[5] = setCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff; //CRC代码低位在前
sendBuf[7] = crcData >> 8; //高位在后
sendCount = 8;
Begin_send();
}
/*************************查询uart接收的数据包内容函数 **************************/
////函数功能:丛机根据串口接收到的数据包receBuf[1]里面的内容,即function code执行相应的命令
/********************************************************************************/
void checkComm0Modbus(void) //10ms内必须响应接收数据
{
uint crcData;
uint tempData;
uint temp;
if(receCount > 4) //如果接收到数据
{
switch(receBuf[1])
{
case 1: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 1)
{
readCoils(); //读取线圈输出状态(一个或多个)
}
receCount = 0;
}
}
break;
}
case 2: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 2)
{
readInPutCoils(); //读取线圈输入状态(一个或多个)
}
receCount = 0;
}
}
break;
}
case 3: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 3)
{
readRegisters(); //读取保持寄存器(一个或多个)
}
receCount = 0;
}
}
break;
}
case 4: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 4)
{
readInPutRegisters(); //读取输入寄存器(一个或多个)
}
receCount = 0;
}
}
break;
}
case 5: //读取寄存器(一个或多个)
{
if(receCount >= 8) //从询问数据包格式可知,receCount应该等于8 ,接收完成一组数据应该关闭接收中断
{
if(receBuf[0]==LocalAddr) //核对地址
{
crcData = crc16(receBuf,6); //核对校验码
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 5)
{
forceSingleCoil(); //强置单个线圈 状态
}
receCount = 0;
}
}
break;
}
case 6: if(receCount >= 8)
{
if(receBuf[0]==LocalAddr)
{
crcData = crc16(receBuf,6);
temp=receBuf[7];
temp=(temp<<8)+receBuf[6];
if(crcData == temp)
if(receBuf[1] == 6)
{
presetSingleRegister(); //预置单个保持寄存器
}
receCount = 0;
}
}
break;
case 15://设置多个线圈
tempData = receBuf[6];
tempData += 9; //数据个数
if(receCount >= tempData)
{
if(receBuf[0]==LocalAddr )
{
crcData = crc16(receBuf,tempData-2);
if(crcData == (receBuf[tempData-1]<<8)+ receBuf[tempData-2])//更改了??
{
forceMultipleCoils();
}
}
receCount = 0;
}
break;
case 16: //设置多个寄存器
{
tempData = (receBuf[4]<<8) + receBuf[5]; //设置寄存器个数
tempData = tempData * 2; //数据个数= 寄存器*2
tempData += 9; //从询问数据包格式可知,receCount应该等于9+byteCount
if(receCount >= tempData)
{
if(receBuf[0]==LocalAddr ) //核对地址
{
crcData = crc16(receBuf,tempData-2);
temp=receBuf[tempData-1];
temp=(temp<<8)+receBuf[tempData-2];
if(crcData == temp)
{
presetMultipleRegisters();
}
}
receCount = 0;
}
break;
}
default: break;
}
}
}
/********************以下为移植的数据修改区**************************************************/
//取线圈状态 返回0表示成功
uint getCoilVal(uint addr,uint *tempData)
{
uint tempAddr;
tempAddr = addr;//只取低8位地址
switch(tempAddr)
{
// case RWSTATUES0: *tempData = RWstatus0; break;
default: break;
}
return 0;
}
uint setCoilVal(uint addr,uint tempData)//设定线圈状态 返回0表示成功
{
uint tempAddr;
tempAddr = addr;
switch(tempAddr)
{
// case RWSTATUES0: RWstatus0= tempData; break;
default: break;
}
return 0;
}
/*******************************读取寄存器内容函数 返回0表示成功**************************/
uint getRegisterVal(uint addr,uint *tempData)
{
switch(addr)
{
case WEIDU: { *tempData =Temperature ; break; }
case SHIDU: { *tempData =Humidity ; break; }
case CO2: { *tempData =Co2 ; break; }
case RIZHAO: { *tempData =Rizhao ; break; }
default: break;
}
return 0;
}
/*******************************设置寄存器内容函数 *返回0表示成功*************************/
uint setRegisterVal(uint addr,uint tempData)
{
switch(addr)
{
case WEIDU: {Temperature=tempData ;break; }
case SHIDU: { Humidity=tempData ;break; }
case CO2: { Co2=tempData ;break; }
case RIZHAO: { Rizhao=tempData ; break; }
}
return 0;
}[/mw_shl_code]
一周热门 更多>