51单片机 调试通过的 modbus RTU 源码
本帖最后由 gmajvfhpa 于 2013-11-14 13:25 编辑东拼西凑的程序。
STC12C5A60S2 单片机24M晶振,别的单片机可能要更改 串口初始化函数中波特率相关代码 与中断0 中断时间相关的代码
总体思想:在串口中断中判断数据 是否接收到 完整的帧,是则关中断。在主循环中 处理接收到的帧,处理好后开口中断。
#define OUTTIME 15//两数据帧最小间隔毫秒
#define MOD_ADDR 1 //本modbus 地址
uint8 receCount; //接收到的字节个数
uint8 idata receBuf; //发送接收缓冲区
uint8 idata receTimeOut; //接收超时
// 串行中断程序
void uartIntProc() interrupt 4
{
if(RI)
{
RI = 0;
if(receTimeOut==0)//两次接收的间隔时间大于OUTTIME receTimeOut在中断中每隔1ms减1
{
if(receCount>3) //如已收到的字节大于3个, 则认为已接到一帧数据,关中断等待解析函数处理 解析函数判断 接收到的字节数与 是否超时 就可确定是否有数据包
{ //解析完后,接到的到字节数receCount清零
ES = 0; //关串口中断 如已收到一个数据包,则要到处理好之后 由处理函数打开
return;
}
else
receCount = 0;
}
receTimeOut = OUTTIME;//置计时寄存器 该寄存器 在中断0中,每隔1ms自动减1
receBuf = SBUF;
// ACC = SBUF;
// if(P != RB8)
// checkoutError = 2; //偶校验出错
receCount++; //已接收到的数据量加1
receCount &= 0x0f; //最多一次只能接收16个字节
}
}
/**************************************************************************************************
NAME : function_MODBUS //检查与处理uart0数据
INPUT : NO
OUTPUT : NO
FUNCTION :
执行MODBUS功能函数
**************************************************************************************************/
void function_MODBUS(void)
{
bit bt;
if(receCount > 3) //接收到的数据大于4
{
if(receTimeOut==0) // 离上次接收到数据的最大间隔时 限 已等于0
{
bt = !checkPACK_MODBUS();// 校验接收数据包的正确性 正确返回零,错误返回非零值。
if((receBuf == MOD_ADDR) && bt ) //是本机地址
{
switch(receBuf)
{
case 1://读取线圈状态(读取点 16位以内)
break;
case 3://读取保持寄存器(一个或多个)
read_reg();//读寄存器
sendPACK_MODBUS( ); //将CRC加入数据尾部,并发送数据包
break;
case 5://强制单个线圈
case 6://设置单个寄存器
TX_NByte(receBuf,receCount);
break;
default:
break;
}
}
receCount =0;//处理好数据后,接收到的字节个数清零
ES = 1; //开串口中断 如已收到一个数据包,则要到处理好之后才能再开接收数据
}
}
}
代码基本调通,已可以与 Modbus调试精灵 通信。不过有一疑问 ,在波特率9600时,理论上 “OUTTIME 15//两数据帧最小间隔毫秒”为3ms就够,实际要设到9以上才行,好久没搞懂
纯顶支持。 关中断就不能保证每一帧都能接收到了啊 支持搂主,学习一下 rantingting 发表于 2013-11-14 13:04 static/image/common/back.gif
关中断就不能保证每一帧都能接收到了啊
在已接收到的一帧没处理前,确实是这样的。也想知道这样处理还会有什么别的不良后果 gmajvfhpa 发表于 2013-11-14 13:07 static/image/common/back.gif
在已接收到的一帧没处理前,确实是这样的。也想知道这样处理还会有什么别的不良后果 ...
开缓冲区吧,中断一直接收,主程序读程序就行,不会丢数据,需要耗一些ram rantingting 发表于 2013-11-14 13:09 static/image/common/back.gif
开缓冲区吧,中断一直接收,主程序读程序就行,不会丢数据,需要耗一些ram ...
嗯,这是个好办法。一般要开几个帧的缓存?
谢谢 只有接收中断,发送不在中断的发 smartmeter 发表于 2013-11-14 13:33 static/image/common/back.gif
只有接收中断,发送不在中断的发
发送在 处理函数内 在处理函数发,发送时就不能做别的事情了,程序结构不好。 smartmeter 发表于 2013-11-14 13:44 static/image/common/back.gif
在处理函数发,发送时就不能做别的事情了,程序结构不好。
这还真是个不足,看到人家代码就是在 中断中发送的,还以为没什么用,把它改过来了{:mad:} 中断中发可以的,关键是你怎样处理数据。。。。。用发送中断吧! 介个Modbus调试精灵我收了。谢谢 呵呵呵 gmajvfhpa 发表于 2013-11-14 13:12 static/image/common/back.gif
嗯,这是个好办法。一般要开几个帧的缓存?
谢谢
看你ram大小了,我一般开5个帧以上,{:lol:} ,如果你能及时处理数据,帧又比较大的话,其实两个帧就够了,因为串口还是比较慢的 路过收下, {:sweat:} 少了3个dll,精灵没法运行! 是偶的系统问题? 顺便传上来:
收了!非常感谢
最近在学习Modbus,学习学习 感谢分享,楼主继续给力 非常感谢分享! 我有个传感器是modbus通信的 关中断易造成接收数据丢失,可以采用乒乓缓冲方法 一直在研究这方面的东西,学习学习。非常感谢
页:
[1]