#include "modbus.h"
#include "crc16.h"
#include "uart.h"
extern u8 ReceiveBuf[MaxDataLen];
extern u8 RecIndexLen;
u8 SendBuf[MaxDataLen] = {0};
u16 StartRegAddr = 0;
u8 err = 0; //错误代码
u8 HoldReg[16] = {1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8}; //存储8路输出功率值
/*
错误代码说明:
0x01 不是支持的功能码
0x02 起始地址不在规定范围内
0x03 寄存器数量不在规定范围内
0x04 数据校验错误
*/
//处理接收到的数据
// 接收: [地址][功能码][起始地址高][起始地址低][总寄存器数高][总寄存器数低][CRC低][CRC高]
void DisposeReceive( void )
{
u16 CRC16 = 0, CRC16Temp = 0;
if( ReceiveBuf[0] == SlaveID ) //地址等于本机地址 地址范围:1 - 32
{
CRC16 = App_Tab_Get_CRC16( ReceiveBuf, RecIndexLen - 2 ); //CRC校验 低字节在前 高字节在后 高字节为报文最后一个字节
CRC16Temp = ( ( u16 )( ReceiveBuf[RecIndexLen - 1] << 8 ) | ReceiveBuf[RecIndexLen - 2] );
if( CRC16 != CRC16Temp )
{
err = 4; //CRC校验错误
}
StartRegAddr = ( u16 )( ReceiveBuf[2] << 8 ) | ReceiveBuf[3];
if( StartRegAddr > 0x07 )
{
err = 2; //起始地址不在规定范围内 00 - 07 1 - 8号通道
}
if( err == 0 )
{
switch( ReceiveBuf[1] ) //功能码
{
case 3: //读多个寄存器
{
Modbus_03_Slave();
break;
}
case 6: //写单个寄存器
{
Modbus_06_Slave();
break;
}
case 16: //写多个寄存器
{
Modbus_16_Slave();
break;
}
default:
{
err = 1; //不支持该功能码
break;
}
}
}
if( err > 0 )
{
SendBuf[0] = ReceiveBuf[0];
SendBuf[1] = ReceiveBuf[1] | 0x80;
SendBuf[2] = err; //发送错误代码
CRC16Temp = App_Tab_Get_CRC16( SendBuf, 3 ); //计算CRC校验值
SendBuf[3] = CRC16Temp & 0xFF; //CRC低位
SendBuf[4] = ( CRC16Temp >> 8 ); //CRC高位
Uart1_Send( SendBuf, 5 );
err = 0; //发送完数据后清除错误标志
}
}
}
/*
函数功能:读保持寄存器 03
主站请求报文: 0x01 0x03 0x0000 0x0001 0x840A 读从0开始的1个保持寄存器
从站正常响应报文: 0x01 0x03 0x02 0x09C4 0xBF87 读到的2字节数据为 0x09C4
*/
void Modbus_03_Slave( void )
{
u16 RegNum = 0;
u16 CRC16Temp = 0;
u8 i = 0;
RegNum = ( u16 )( ReceiveBuf[4] << 8 ) | ReceiveBuf[5]; //获取寄存器数量
if( ( StartRegAddr + RegNum ) < 9 ) //寄存器地址+寄存器数量 在规定范围内
{
SendBuf[0] = ReceiveBuf[0];
SendBuf[1] = ReceiveBuf[1];
SendBuf[2] = RegNum * 2;
for( i = 0; i < RegNum; i++ ) //读取保持寄存器内的值
{
SendBuf[3 + i * 2] = HoldReg[StartRegAddr * 2 + i * 2];
SendBuf[4 + i * 2] = HoldReg[StartRegAddr * 2 + i * 2 + 1];
}
CRC16Temp = App_Tab_Get_CRC16( SendBuf, RegNum * 2 + 3 ); //获取CRC校验值
SendBuf[RegNum * 2 + 3] = CRC16Temp & 0xFF; //CRC低位
SendBuf[RegNum * 2 + 4] = ( CRC16Temp >> 8 ); //CRC高位
Uart1_Send( SendBuf, RegNum * 2 + 5 );
}
else
{
err = 3; //寄存器数量不在规定范围内
}
}
/*
函数功能:写单个保持寄存器 06
主站请求报文: 0x01 0x06 0x0000 0x1388 0x849C 写0号寄存器的值为0x1388
从站正常响应报文: 0x01 0x06 0x0000 0x1388 0x849C 0号寄存器的值为0x1388
*/
void Modbus_06_Slave( void )
{
u16 RegValue = 0;
u16 CRC16Temp = 0;
RegValue = ( u16 )( ReceiveBuf[4] << 8 ) | ReceiveBuf[5]; //获取寄存器值
if( RegValue < 1001 ) //寄存器值不超过1000
{
HoldReg[StartRegAddr * 2] = ReceiveBuf[4]; //存储寄存器值
HoldReg[StartRegAddr * 2 + 1] = ReceiveBuf[5];
SendBuf[0] = ReceiveBuf[0];
SendBuf[1] = ReceiveBuf[1];
SendBuf[2] = ReceiveBuf[2];
SendBuf[3] = ReceiveBuf[3];
SendBuf[4] = ReceiveBuf[4];
SendBuf[5] = ReceiveBuf[5];
CRC16Temp = App_Tab_Get_CRC16( SendBuf, 6 ); //获取CRC校验值
SendBuf[6] = CRC16Temp & 0xFF; //CRC低位
SendBuf[7] = ( CRC16Temp >> 8 ); //CRC高位
Uart1_Send( SendBuf, 8 );
}
else
{
err = 3; //寄存器数值不在规定范围内
}
}
/*
函数功能:写多个连续保持寄存器值 16
主站请求报文: 0x01 0x10 0x7540 0x0002 0x04 0x0000 0x2710 0xB731 写从0x7540地址开始的2个保持寄存器值 共4字节
从站正常响应报文: 0x01 0x10 0x7540 0x0002 0x5A10 写从0x7540地址开始的2个保持寄存器值
*/
void Modbus_16_Slave( void )
{
u16 RegNum = 0;
u16 CRC16Temp = 0;
u8 i = 0;
RegNum = ( u16 )( ReceiveBuf[4] << 8 ) | ReceiveBuf[5]; //获取寄存器数量
if( ( StartRegAddr + RegNum ) < 9 ) //寄存器地址+寄存器数量 在规定范围内
{
for( i = 0; i < RegNum; i++ ) //存储寄存器设置值
{
HoldReg[StartRegAddr * 2 + i * 2] = ReceiveBuf[i * 2 + 7];
HoldReg[StartRegAddr * 2 + 1 + i * 2] = ReceiveBuf[i * 2 + 8];
}
SendBuf[0] = ReceiveBuf[0];
SendBuf[1] = ReceiveBuf[1];
SendBuf[2] = ReceiveBuf[2];
SendBuf[3] = ReceiveBuf[3];
SendBuf[4] = ReceiveBuf[4];
SendBuf[5] = ReceiveBuf[5];
CRC16Temp = App_Tab_Get_CRC16( SendBuf, 6 ); //获取CRC校验值
SendBuf[6] = CRC16Temp & 0xFF; //CRC低位
SendBuf[7] = ( CRC16Temp >> 8 ); //CRC高位
Uart1_Send( SendBuf, 8 );
}
else
{
err = 3; //寄存器数量不在规定范围内
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
STM8S_UARTV0.1.zip (56个子文件)
STM8S_UARTV0.1
main.c.orig 2KB
UART.ewd 16KB
UART.ewt 157KB
Debug
Obj
UART.pbd 262KB
crc16.pbi 3KB
timer4.o 10KB
timer4.pbi.xcl 11KB
main.o 9KB
modbus.pbi 227KB
delay.pbi.xcl 11KB
uart.o 21KB
uart.pbi 252KB
delay.pbi 2KB
main.pbi.xcl 11KB
modbus.o 16KB
main.pbi 252KB
UART.pbd.linf 422B
uart.pbi.xcl 11KB
timer4.pbi 220KB
delay.o 9KB
crc16.pbi.xcl 11KB
modbus.pbi.xcl 11KB
crc16.o 8KB
List
LED.map 18KB
Exe
UART.hex 6KB
LED.out 50KB
UART.ewp 57KB
BuildLog.log 2KB
TermIO.log 0B
UART.eww 158B
main.h 213B
HardWare
uart.c.orig 2KB
timer4.h 141B
uart.h 340B
timer4.c 702B
uart.c 2KB
modbus.c 7KB
crc16.c.orig 4KB
modbus.c.orig 7KB
crc16.h 233B
crc16.c 5KB
uart.h.orig 244B
delay.c 2KB
delay.h 375B
timer4.c.orig 658B
modbus.h 255B
modbus.h.orig 168B
settings
UART.Debug.cspy.bat 2KB
UART.dnx 2KB
UART.dbgdt 50KB
UART.Debug.driver.xcl 140B
UART.Debug.general.xcl 319B
UART.Debug.cspy.ps1 2KB
UART.wsdt 31KB
UART.dep 8KB
main.c 2KB
共 56 条
- 1
资源评论
- mcaeg2024-05-05基本发送接收无问题,功能需要自己完善
- 胖哥王老师2020-11-25还可以,主要是计算CRC有点用
嵌入式@hxydj
- 粉丝: 11w+
- 资源: 174
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- HtmlMate标签使用详解中文最新版本
- ATM机旁危险物品检测数据集VOC+YOLO格式1251张5类别.zip
- 网页优化meta标签使用方法及规则中文最新版本
- 网页万能复制 浏览器插件
- IMG_20241123_093226.jpg
- JavaScript的表白代码项目源码.zip
- springboot vue3前后端分离开发入门介绍,分享给有需要的人,仅供参考
- 全国297个地级市城市辖区数据1990-2022年末实有公共汽车出租车数人均城市道路建成区绿地面积供水供气总量医院卫生机构数医生人数GDP第一二三产业增加值分行业从业人员水资源农产品产量利用外资
- Python客流量时间序列预测模型.zip
- 故障预测-灰色预测模型C++源码.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功