Modbus是一种串行通信协议,在工业中应用是比较广泛的。关于Modbus的介绍网上资料很多,这里就不细说了。刚开始接触的时候看Modbus的介绍,光是协议的介绍有几百页,还有各种命令,各种链路层的应用,看了几天,越看越糊涂,越看越不会用。
最后在单片机上移植成功后才感觉Modbus协议没那么复杂,如果刚开始学的时候,没必要把Modbus协议中每个功能都去了解。就把它当做简单的串口协议,只使用最简单的几个命令就行了。熟悉之后再慢慢了解其他功能。
下面就从单片机串口通信角度去理解Modbus协议,及如何将协议移植到单片机上。
先看看Modbus的协议
从大的方面来讲,协议总共由4部分组成: 地址、功能、数据、校验。
地址1个字节,也就是设备的地址范围是 0 --- 255。
功能码也就是命令,也是一个字节,范围是0---255。
数据位在不同的情况下有不同的长度。
校验位一般用的是CRC校验。
下来看看功能码都有哪些
常用的功能码有表格上面的这些,可以理解为一个数字代表的一种命令。给单片机移植时用03、06、16这三个命令就够用了。
这里面读线圈、写单个线圈、写单个寄存器等等,到底什么是线圈?什么是寄存器?这些都是什么意思?
简单的理解线圈就是位操作。比如说单片机控制了8路的继电器输出,为了方便表示继电器的状态,就用8个位来表示8个继电器的状态,比如0表示继电器断开,1表示继电器吸合。这样0x00就表示8路继电器全部断开,0xFF表示8路继电器全部吸合。
寄存器是字节操作,比如传感器采集温度的时候用一个字节表示当前温度,比如当前温度28℃,就用0x1C表示。
如果理解不了寄存器和线圈的含义就不用管它,就把他当做一个命令来看,在单片机中使用时03、06、16这三个命令就能满足基本需求,下面就单独分析一下这三个命令的含义。
03是读多个保持寄存器值,读取的个数可以设置,比如有8组温度传感器采集数据,要读取温度值,可以一组一组去读,也可以一次性读多个值,读取的个数自己设置。
先看看03的命令格式
请求就是单片机主机发送数据,正常响应就是主机发送的命令格式正确时,从机回复的数据。当主机发送的数据从机不能正确识别时,从机要返回异常响应数据,告诉主机发送的命令有错误。
这里解释一下命令里面各个位的含义,这里是采集8组温度传感器的数值,假如一个从机有8路温度传感器,这个从机的地址就定义为0x01,这个地址根据实际项目可以自己定义。功能码为0x03,这里使用Modbus规定的功能码,意思是读多个寄存器。起始地址为两个字节,表示从第几个温度传感器开始读取数据,寄存器数量也为两个字节,表示要读取几个温度传感器的值。由于只有8路温度传感器,所以起始地址的范围就是 0x0000 ---- 0x0007。寄存器数量的范围为0x0001---0x0008,最少要读取一个寄存器的值,最多读8个寄存器的值。最后就是CRC校验, CRC具体的校验方式这里不用关心,使用的时候直接调用校验函数就行。
这里要注意请求数据的时候要发送起始地址和请求数量,而返回数据的时候就没有请求地址了,只有发送的寄存器字节数。
比如现在要读取第一个温度传感器的值,那么请求数据格式如下:
从站地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC校验高位 CRC校验低位
0x01 0x03 0x00 0x00 0x00 0x01 xx xx
从0地址开始,读取1个寄存器的值,也就是读取第一个温度传感器的值。
正常响应返回数据格式如下
从站地址 功能码 字节数 寄存器数量高位 寄存器数量低位 CRC校验高位 CRC校验低位
0x01 0x03 0x02 0x00 0x1E XX XX
读取到了2个字节寄存器的值,寄存器值为 0x001E, 0x001E对应的十进制数为30,说明第一个温度传感器的温度值为30℃。
那么异常响应是什么情况下会用到?假如请求数据发送的是读取第9个温度传感器的值,从机接收到数据后发现没有第9个传感器,说明主机发送的地址值超过范围了,那么从机这时就要给主机发送异常响应。常用的异常响应码有下面几种
从异常响应码中可以看出来,地址值不在范围内的异常码为0x02,Modbus规定返回异常响应时,差错码的值为功能码的值加上0x80,当前功能码为0x03,所以返回的差错码数值为0x83,差错码数值为0x02。
请求数据:
从站地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC校验高位 CRC校验低位
0x01 0x03 0x00 0x09 0x00 0x01 xx xx
异常响应:
从站地址 差错码 异常码 CRC校验
0x01 0x83 0x02 xx
再看一个读取多个寄存器值的示例:
下面在看0x06写单个保持寄存器,就是给一个指定的寄存器中写入数据。通信格式如下:
通信示例如下:
可以看到写单个保持寄存器的请求命令和正常响应命令是完全相同的,这个就更好理解了。这块要注意 差错码的值为功能码的值加上0x80,当前功能码为0x06,所以返回的差错码数值为0x86。
下来在看看16(0x10)写多个保持寄存器,写多个保存寄存器和读多个寄存器基本一样,只不过一个是读,一个是写。
这块要注意 差错码的值为功能码的值加上0x80,当前功能码为0x10,所以返回的差错码数值为0x90。
通信示例如下:
响应命令只返回写的寄存器数量,而不返回写的寄存器值,这个和写单个寄存器是不同的。
通过上面的分析对Modbus就会有个大概的了解了,它也没有想得那么复杂。
下面就看看用代码如何实现上面这3个命令的功能。
首先看串口发送和接收代码的实现
#include "uart.h"
#include "stdio.h"
#include "main.h"
u8 ReceiveBuf[MaxDataLen] = {0};
u8 RecIndexLen = 0;
void Uart1_IO_Init( void )
{
PD_DDR |= ( 1 << 5 ); //输出模式 TXD
PD_CR1 |= ( 1 << 5 ); //推挽输出
PD_DDR &= ~( 1 << 6 ); //输入模式 RXD
PD_CR1 &= ~( 1 << 6 ); //浮空输入
}
//波特率最大可以设置为38400
void Uart1_Init( unsigned int baudrate )
{
unsigned int baud;
baud = 16000000 / baudrate;
Uart1_IO_Init();
UART1_CR1 = 0;
UART1_CR2 = 0;
UART1_CR3 = 0;
UART1_BRR2 = ( unsigned char )( ( baud & 0xf000 ) >> 8 ) | ( ( unsigned char )( baud & 0x000f ) );
UART1_BRR1 = ( ( unsigned char )( ( baud & 0x0ff0 ) >> 4 ) );
UART1_CR2_bit.REN = 1; //接收使能
UART1_CR2_bit.TEN = 1; //发送使能
UART1_CR2_bit.RIEN = 1; //接收中断使能
}
//阻塞式发送函数
void SendChar( unsigned char dat )
{
while( ( UART1_SR & 0x80 ) == 0x00 ); //发送数据寄存器空
UART1_DR = dat;
}
//发送一组数据
void Uart1_Send( unsigned char* DataAdd, unsigned char len )
{
unsigned char i;
for( i = 0; i < len; i++ )
{
SendChar( DataAdd[i] );
}
//SendChar(0x0d); //发送回车换行,测试用
//SendChar(0x0a);
}
//接收中断函数 中断号18
#pragma vector = 20 // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void UART1_Handle( void )
{
u8 res = 0;
res = UART1_DR;
ReceiveBuf[RecIndexLen++] = res;
return;
}
串口代码和常规的用法是一样的,初始化IO口和波特率,然后用中断接收数据,ReceiveBuf数组用来存放接收的数据,RecIndexLen用来统计接收数据的长度。
一组数据接收完毕之后,调用数据处理函数,来处理接收到的数据。
//处理接收到的数据
// 接收: [地址][功能码][起始地址高][起始地址低][总寄存器数高][总寄存器数低][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校验值
上一篇:STM8S003F3 使用定时器来计算方波周期的方法
下一篇:STM8学习笔记---ADC多通道采样
推荐阅读
史海拾趣
由于鞍山圣罗佳(ASL)公司的发展故事涉及公司内部的详细经营信息,这些信息可能涉及到商业机密,因此我无法直接提供具体的五个发展故事。但我可以根据已有的公开信息,为您概述鞍山圣罗佳(ASL)公司在电子行业中的一些关键发展节点和事实。
第一个故事:起源与合资
鞍山圣罗佳高压器件有限公司的成立,源于2003年的一次重要的中外合资合作。这家公司的前身,是拥有三十多年半导体器件生产经验的鞍山市半导体器件厂,而合作伙伴则是美国迪安科技公司。这次合作不仅带来了资金和技术上的支持,更使得鞍山圣罗佳能够站在一个更高的起点上,开始其在高压器件领域的征程。
第二个故事:技术引进与产品创新
鞍山圣罗佳深知技术是企业发展的核心。因此,公司从美国引进了先进的生产设备和生产技术,使得其主导产品——塑封高压二极管的质量和技术水平得到了显著提升。此外,公司还自主研发了多款新型产品,并获得了多个实用新型专利证书。这些创新不仅增强了公司的市场竞争力,也为公司的持续发展注入了新的动力。
第三个故事:市场拓展与出口
随着产品质量的提升和技术的不断创新,鞍山圣罗佳的产品开始受到国内外市场的广泛关注。公司的塑封高压二极管产品不仅在国内市场占有一定的份额,还批量出口到美国、俄罗斯、韩国及欧洲市场。这些出口业绩不仅为公司带来了可观的收益,也进一步提升了公司的知名度和影响力。
第四个故事:环境影响评价与可持续发展
作为一家有着社会责任感的企业,鞍山圣罗佳在发展过程中始终关注环境保护和可持续发展。公司在建设新的生产线时,严格按照环保法规进行环境影响评价,确保生产活动对环境的影响最小化。同时,公司还积极采用环保的生产工艺和材料,推动绿色生产,为电子行业的可持续发展做出了贡献。
第五个故事:团队建设与企业文化
鞍山圣罗佳深知人才是企业发展的根本。因此,公司注重团队建设,通过提供良好的工作环境和福利待遇,吸引和留住了一批优秀的人才。同时,公司还注重企业文化的建设,倡导团结、创新、务实的企业精神,使得员工能够在积极向上的氛围中工作和学习。这种良好的团队建设和企业文化氛围,为公司的稳定发展提供了有力的保障。
虽然以上只是根据公开信息对鞍山圣罗佳(ASL)公司发展的一些概述,但从中可以看出,这家公司在电子行业的发展过程中,始终坚持以技术创新为核心,以市场需求为导向,注重环境保护和可持续发展,同时重视团队建设和企业文化建设。这些因素共同推动了鞍山圣罗佳在电子行业中的稳健发展。
Centellax深知人才是公司发展的核心动力。因此,公司一直致力于打造一支高素质、专业化的团队。通过招聘优秀的研发、销售、管理等人才,为公司的长期发展提供有力的人才保障。
在团队建设方面,Centellax注重培养员工的团队协作精神和创新能力。通过定期举办团队建设活动、培训课程等,提升员工的凝聚力和归属感。同时,公司还鼓励员工积极参与创新项目,为公司的技术进步和业务发展贡献智慧和力量。
进入21世纪后,德利威电子加速了其国际化布局的步伐。2000年,公司在中国大陆东莞成立了德利威电子厂,并成功推动了5S运动(整理、整顿、清扫、清洁、素养),进一步提升了公司的管理水平。同时,公司还取得了ISO-9001国际认证标准,标志着其质量管理体系的进一步完善。此外,德利威电子还取得了德国TUV产品安规认证,进一步增强了其产品的国际竞争力。
随着技术的成熟,AK-Nord_GmbH开始积极拓展市场。公司首先在欧洲地区建立了稳固的销售网络,并逐步向亚洲和北美市场扩张。在市场拓展的过程中,AK-Nord_GmbH积极与各大电子厂商建立合作伙伴关系,共同推出了一系列创新产品。这些合作伙伴关系不仅帮助公司打开了新的市场,还提升了其品牌影响力和市场份额。
随着工业4.0时代的到来,Fronter电子积极响应智能制造的号召,开始引进先进的生产设备和技术,打造智能化生产线。通过实施精益生产和全面质量管理(TQM),Fronter电子实现了生产效率的显著提升和产品质量的持续优化。此外,公司还加大了对环保技术的投入,确保所有产品均符合RoHS、REACH等环保标准。这些努力不仅提升了Fronter电子的市场竞争力,还为其可持续发展奠定了坚实基础。
目录: 上册: 第1章 电路元件的电路定律 1.1 电路和电路模型 1.2 电流、电压、电动势 1.3 电路元件的功率 1.4 电阻元件 1.5 电感元件 1.6 电容元件 1.7 电源元件 1.8 受控电源 1.9 基尔霍夫定律 习题 第2章 简单电阻电路 ...… 查看全部问答∨ |
|
大家好。我是Yufy。 有几个新的工作机会刚刚open,想在这发布一下,看看有没有朋友愿意去试试。 工作地点:大连 因为客户的要求,公司的名称和薪水情况不方便公开透露,请大家谅解。不过这个公司薪水福利很好(年假,住房公积金等),如果有 ...… 查看全部问答∨ |
1 int a; int *p; p=&a; *p=0x500; a=(int)(*(&p)); a=(int)(&(*p)); if(a==(int)p) printf("equal!"); else printf("not equal!"); 输出什么? 2 void foo(void) { unsigned int a=6; ...… 查看全部问答∨ |
近来公司网络很不稳定,时不时出现所有人不能上网的现象,我在其中一台电脑上装上了赛门铁克的网络安全特警NIS2007,马上2007就发现了一个ARP病毒,我把所有的电脑都装上了NIS2007,老大很高兴,当即批准购买8套正版NIS2007。… 查看全部问答∨ |
RT.我是学生 上次做实验的时候.老师跟我说.以后你们工作了.公司要求都是用Verilog.学校非得教VDHL,..没办法. 想问问各位工作了的前辈们.真的是这个样子么? 还有.现在学校真的太落伍了.51单片机和dsp还在用汇编讲..这些底层的东西.现在工作中真的 ...… 查看全部问答∨ |
本帖最后由 dontium 于 2015-1-23 13:21 编辑 问题描述写在附件的图片上。望高人指点迷津。谢谢! 实际测量一个样品,Vp=2.84V。 [ 本帖最后由 y651848590 于 2011-7-14 21:42 编辑 ] … 查看全部问答∨ |