历史上的今天
返回首页

历史上的今天

今天是:2024年11月11日(星期一)

正在发生

2019年11月11日 | 用PIC18F4520与发电机上的电表实现MUDBUS通信

2019-11-11 来源:51hei

本软件可分为以下五个部分,第一部分是状态设定和位置监测模块,其中发电车的行车和发电状态的设定是由一个船型开关决定的,当开关闭合时,为发电状态,反之为行车状态,步进电机控制油门的开合,但考虑到异常情况,用一个常开型开关实时监测步进电机是否转动到了极限位置;第二部分为LCD液晶显示,主要将串口通信得到的发电机输出电的频率fre、发电机输出电的电流current以及控制步进电机转动快慢的方波频率mtfre这三个参数实时显示在LCD液晶上。第三部分为单片机与发电机上的仪表之间的Modbus-RTU串口通信,通过软件的实时发送和接收可以得到发电机输出电的频率和电流等参数;第四部分为利用定时中断实现频率可调的方波输出,根据发电机的频率与额定频率50HZ的比较来决定输出方波的频率,而方波的频率之所以可以实时变化的原因是通过改变定时器的初值来实现的,改变了定时器的初值,则改变了定时时间的大小,在每一次溢出中断产生时,置反某一个I/O口的电平,从而实现了频率可调的方波输出;第五部分是步进电机的控制模块,这里需要了解步进电机的工作原理以及驱动原理,这个系统采用专用驱动器驱动步进电机进行转动,驱动器上的输入信号包括脉冲信号、方向信号和使能信号,只要将这三种信号按照要求进行输入,驱动器就可以控制步进电机进行正常转动;


  整体的软件功能是在几个模块函数的相互联系相互调用的情况下实现的,每一个模块有自己的专用函数,在编写程序时,用特殊的专用的函数名来对各个模块的函数进行命名,这样方便查找和修改。


  我觉得大家感兴趣的应该是MODBUS通信,因为用到这种通信的一般是工业仪器仪表,所以我想给大家介绍一下,我在编写这一块时的问题和解决办法。

  

1. Modbus-RTU串口通信模块

通信协议:该模块是整个软件的重点部分,实现发电车上的电力仪表与单片机之间的实时通信,得到系统所要提取的发电机的频率和电流。Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络和其它设备之间可以通信。发电机上的电力仪表本身规定用的通信协议为RS485接口Modbus-RTU通信协议。当在Modbus网络上通信时,此协议决定了每个控制器必须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行为。如果需要回应,控制器将生成反馈信息并通过Modbus协议发送。


在Modbus协议中,典型的主设备可以为:主机和可编程仪表。典型的从设备主要为:可编程控制器。在系统中,单片机为主设备,发电机上的电力仪表为从设备。主设备可单独和从设备通信,也能以广播方式和所有从设备通信,如果单独通信,从设备返回一消息作为回应,如果是以广播方式查询的,则从设备们不作任何回应。Modbus协议建立了主设备查询的格式:设备(或广播)地址、功能代码、所有要发送的数据、一错误检测域。从设备回应消息也由Modbus协议构成,包括要确认行动的域、任何要返回的数据、和一错误检测域。如果在消息接收过程中发生一错误,或从设备不能执行其命令,从设备将建立一错误消息并把它作为回应发送出去。


(1)查询  查询消息中的功能代码告之被选中的从设备要执行何种功能。数据段包含了从设备要执行功能的任何附加信息。例如功能代码03是要求从设备读保持寄存器并返回它们的内容。数据段必须包含要告之从设备的信息:从何寄存器开始读及要读的寄存器数量。错误检测域为从设备提供了一种验证消息内容是否正确的方法。

查询数据包结构如下:

从机

地址

功能码

起始寄存器地址高字节

起始寄存器地址低字节

数据字节长度高字节

数据字节长度低字节

CRC校验低字节

CRC检验高字节

(2)回应  如果从设备产生一正常的回应,在回应消息中的功能代码是在查询消息中的功能代码的回应。数据段包括了从设备收集的数据:像寄存器值或状态。如果有错误发生,功能代码将被修改以用于指出回应消息是错误的,同时数据段包含了描述此错误信息的代码。错误检测域允许主设备确认消息内容是否可用。

回应数据包结构:

从机地址

功能码

数据字长

数据段

CRC校验

低字节

CRC检验

高字节

(3)两种传输方式

控制器能设置为两种传输模式:ASCII或RTU中的任何一种在标准的Modbus网络通信。用户选择想要的模式,包括串口通信参数(波特率、校验方式等),在配置每个控制器的时候,在一个Modbus网络上的所有设备都必须选择相同的传输模式和串口参数。相对来说,RTU模式传输效率更高,因此,在当前普遍的生产环境中RTU模式获得了广泛应用,而ASCII模式只作为特殊情况下的可选项。


ASCII模式

当控制器设为在Modbus网络上以ASCII(美国标准信息交换代码)模式通信,一个信息中的每8个比特作为2个ASCII字符传输,如数值63H用ASCII方式时,需发送两个字节,即ASCII“6"(0110110)和ASCII”3“(0110011),ASCII字符占用的位数有7位和8位,国际通用7位为多。这种方式的主要优点是字符发送的时间间隔可达到1秒而不产生错误。


代码系统

· 十六进制,ASCII字符0...9,A...F

· 消息中的每个ASCII字符都是一个十六进制字符组成

每个字节的位

· 1个起始位

· 7个数据位,最小的有效位先发送

· 1个奇偶校验位,无校验则无

1个停止位(有校验时),2个Bit(无校验时)

错误检测域

· LRC(纵向冗长检测)

RTU模式

当控制器设为在Modbus网络上以RTU模式通信,在消息中的每个8Bit字节按照原值传送,不做处理,如63H,RTU将直接发送01100011。这种方式的主要优点是:数据帧传送之间没有间隔,相同波特率下传输数据的密度要比ASCII高,传输速度更快。


代码系统

8位二进制,十六进制数0...9,A...F

消息中的每个8位域都是一或两个十六进制字符组成

每个字节的位

1个起始位

8个数据位,最小的有效位先发送

1个奇偶校验位,无校验则无

1个停止位(有校验时),2个Bit(无校验时)

(4)数据校验方式

CRC校验

CRC域是两个字节,包含一16位的二进制值。它由传输设备计算后加入到消息中。接收设备重新计算收到消息的CRC,并与接收到的CRC域中的值比较,如果两值不同,则有误。


CRC是先调入一值是全“1”的16位寄存器,然后调用一过程将消息中连续的8位字节和当前寄存器中的值进行处理。仅每个字符中的8Bit数据对CRC有效,起始位和停止位以及奇偶校验位均无效。


CRC产生过程中,每个8位字符都单独和寄存器内容相异或(XOR),结果向最低有效位方向移动,最高有效位以0填充。LSB被提取出来检测,如果LSB为1,寄存器单独和预置的值或一下,如果LSB为0,则不进行。整个过程要重复8次。在最后一位(第8位)完成后,下一个8位字节又单独和寄存器的当前值相异或(XOR)。最终寄存器中的值,是消息中所有的字节都执行之后的CRC值。


CRC添加到消息中时,低字节先加入,然后高字节。

CRC-16错误校验程序如下:报文(此处只涉及数据位,不指起始位、停止位和任选的奇偶校验位)被看作是一个连续的二进制,其最高有效位(MSB)首选发送。报文先与X↑16相乘(左移16位),然后看X↑16+X↑15+X↑2+1除,X↑16+X↑15+X↑2+1可以表示为二进制数11000,0000,0000,0101。整数商位忽略不记,16位余数加入该报文(MSB先发送),成为2个CRC校验字节。余数中的1全部初始化,以免所有的零成为一条报文被接收。经上述处理而含有CRC字节的报文,若无错误,到接收设备后再被同一多项式(X↑16+X↑15+X↑2+1)除,会得到一个零余数(接收设备核验这个CRC字节,并将其与被传送的CRC比较)。全部运算以2为模(无进位)。


习惯于成串发送数据的设备会首选送出字符的最右位(LSB-最低有效位)。而在生成CRC情况下,发送首位应是被除数的最高有效位MSB。由于在运算中不用进位,为便于操作起见,计算CRC时设MSB在最右位。生成多项式的位序也必须反过来,以保持一致。多项式的MSB略去不记,因其只对商有影响而不影响余数。


LRC检验

LRC错误校验用于ASCII模式。这个错误校验是一个8位二进制数,可作为2个ASCII十六进制字节传送。把十六进制字符转换成二进制,加上无循环进位的二进制字符和二进制补码结果生成LRC错误校验(参见图)。这个LRC在接收设备进行核验,并与被传送的LRC进行比较,冒号(:)、回车符号(CR)、换行字符(LF)和置入的其他任何非ASCII十六进制字符在运算时忽略不计。


(5)Modbus协议中功能码定义

Modbus功能码在查询数据包和回应数据包里都只占用一个字节,取值范围是1~127。之所以127以上不能使用,是因为Modbus规定当通信出现异常时,功能码+0X80(十进制128)代表异常状态,因此129~255的取值代表异常码。

Modbus相关公共功能码:

代码

名称

操作数量

01

读线圈状态

单个或多个线圈

02

读离散输入状态

单个或多个

03

读保持寄存器

单个或多个

04

读输入寄存器

单个或多个

05

写单个线圈

单个

06

写单个保持寄存器

单个

15

写多个线圈

多个

16

写多个保持寄存器

多个

函数说明:在了解了Modbus协议之后,开始编写Modbus-RTU通信函数。本系统所用的PIC18F4520单片机最小系统只有RS232通信接口,电力仪表提供的是串行异步半双工的RS485通信接口,故需用RS232转RS485转接器实现通信。本模块用USART来编写通信函数,且必须将其设置为串行异步半双工的通信方式,相关USART初始化函数如下:

//USART模块初始化
void USARTinit(void)
{
    
    TXSTAbits.SYNC=0;   //选择异步通信方式
    TXSTAbits.TX9=0;    //选择8位发送数据格式
    //TXSTAbits.TXEN=1;   //允许发送,配置为半双工方式
    
    RCSTAbits.SPEN=1;   //使能串口
    RCSTAbits.RX9=0;    //选择8位接收数据模式
    //RCSTAbits.CREN=1;   //异位模式下,使能接收器

    BAUDCONbits.BRG16=1;   //使能16位的波特率发生器
    TXSTAbits.BRGH=1;   //采用高速波特率
    SPBRGH=832/256;
    SPBRG=832%256;     //波特率设置为9600,系统时钟为32MHZ        
}

在这个函数模块中,电力仪表要收到来自单片机的查询数据包以后,会返回一个回应数据包,而且由于已知要查的频率变量在仪表的74、75两个寄存器以内,发送数据包一共有8个字节,回应数据包一共有9个字节,本来需要根据两个字节之间的传输时间是否大于3.5个字节传输时间来确定是否为新的数据包,但在已知回应数据包字节数的情况下,软件可以简化为直接判断单片机接收到的回应数据包的字节数是否为9。按照这个思路,我们可以打开单片机UASRT的接收中断,首先,将通信方式配置为发送模式,在单片机将查询数据包发送给电力仪表后,将通信方式配置为接收模式,电力仪表发送给单片机一个字节,则接收中断标志位置1,我们将接收到的字节存储在接收数组里面,通过相关函数将接收数组里面有效的信息提取出来加以使用。


接收中断相关函数如下:

void USARTINT(void)

   RCONbits.IPEN=0;      //禁止中断嵌套,禁止中断优先级功能,所以这里不用加上低优先级中断服务函数,但加上问题不大
   INTCON|=0XC0;          //CPU开中断,开启了总中断GIE和外设中断PEIE,即允许外设中断 IPR1bits.RCIP=0;        //设置禁止EUSART接收中断为高优先级
   PIR1bits.RCIF=0;        //清USART接收中断标志
   PIE1bits.RCIE=1;        //允许USART接收中断
}  


#pragma interrupt PIC18F_HIGH_ISR
void PIC18F_HIGH_ISR(void)
{

if(1==PIR1bits.RCIF)                               //rx_index为接收数组的长度
      {
       flag=0;
       PIR1bits.RCIF=0;  //清除接收中断标志位
       if(rx_index          {
           rx_buf[rx_index]=RCREG;
           rx_index++;        //将接收到的数据存进接收数组,并递增计数器rx_index
          }
       if(rx_index==9)   //接收到九个字节,说明一帧结束
         { rx_index=0;flag=1;}        //接受到完整的一帧数据
      }

}

该模块发送函数的设计过程为构建有效信息发送数组,根据发送数组计算CRC校验码,最后将有效信息和CRC校验码构造成一个完整的发送数组再一并发送出去。在这个过程中,比较重要的为CRC计算函数,因为有效信息在已知电力仪表相关寄存器信息以后是确定的,但若校验码错误,即使单片机将发送数组发送给电力仪表,电力仪表经过计算以后与单片机发送过来的CRC校验码不相等,电力仪表则判断为发送信息错误,会发送异常码给单片机,这样通信为不成功,故以下着重介绍CRC计算函数:

//CRC检验函数 1

unsigned short crc(unsigned char *ptr,unsigned char size)

{     

         unsigned short a,b,tmp,CRC16,V;   

         CRC16=0xffff;                 //CRC寄存器初始值  

         for (a=0;a         {   

             CRC16=*ptr^CRC16;     

             for (b=0;b<8;b++)            //8位数据   

             {           

                  tmp=CRC16 & 0x0001;               

                  CRC16 =CRC16 >>1;       //右移一位        

                  if (tmp)           

                  CRC16=CRC16 ^ 0xa001;    //异或多项式      

             }  

             *ptr++;

         }  

         V = ((CRC16 & 0x00FF) << 8) | ((CRC16 & 0xFF00) >> 8); //高低字节转换,这个时候低字节在高八位,高字节在低八位

         return V;  

}

生成CRC-16校验字节的步骤如下:

①例如一个16位寄存器,所有数位均为1。

②该16位寄存器的高位字节与开始8位字节进行“异或”运算。运算结果放入这个16位寄存器。

③把这个16寄存器向右移一位。

④若向右(标记位)移出的数位是1,则生成多项式10,1000,000,0000,001和这个寄存器进行“异或”运算;若向右移出的数位是0,则返回③。

⑤重复③和④,直至移出8位。

⑥另外8位与该十六位寄存器进行“异或”运算。

⑦重复③~⑥,直至该报文所有字节均与16位寄存器进行“异或”运算,并移位8次。

⑧这个16位寄存器的内容即2字节CRC错误校验,被加到报文的最高有效位。

另外,在某些非ModBus通信协议中也经常使用CRC16作为校验手段,而且产生了一些CRC16的变种,他们是使用CRC16多项式X↑16+X↑15+X↑2+1,单首次装入的16位寄存器为0000;使用CRC16的反序X↑16+X↑14+X↑1+1,首次装入寄存器值为0000或FFFFH。

Modbus-RTU通信函数如下:

//modbus-rtu通信得到输出电频率
float modbus_rtu(void)
{
      float a;
      cnttxd=rtu_read_hldreg(LOCALADDR,tx_buf,73,2);   //得到发送数组的字节数
      transmit(tx_buf,cnttxd);                    //发送,cnttxd为发送数组的长度
      while(!flag&&RC4==0);                       //判断接收数组长度是否达到了要求的长度
      if(rtu_data_anlys(rx_buf,9)==1)     //数据分析,检验接收到的数据对不对
              a=receive(rx_buf);              //实时接收到仪表的频率fre
      else
              a=0;
      return a;
}

接口设计:本模块的接口电路已在PIC18F4520单片机最小系统里面集成,值得注意的是本模块虽然使用的是RS232串行通信模块,但是由于仪表的通信接口为RS485,仪表与单片机之间用公—公串口线与RS485转RS232的转接器相连进行通信,故实际中即使RS232串行通讯模块是全双工的,其中的RC6、RC7本可以在同一时间使用,但是在本模块下,必须设置为半双工工作方式。RS232串行通信电路如下:

推荐阅读

史海拾趣

明波通信(BWAVE)公司的发展小趣事

在2002年,一群从海外归来的留学生和技术专家,怀揣着对通信技术的热情与梦想,在上海创立了明波通信技术股份有限公司。他们深知国内在通信领域的技术与海外相比还有较大差距,因此决心将自己在海外学到的先进知识和经验,应用到国内的市场和技术创新中。明波通信从创立之初就致力于数字电视芯片的研究与开发,并逐渐在行业中崭露头角。

博众电气(BOZHONG ELECTRIC)公司的发展小趣事

随着市场需求的不断增长,博众电气意识到传统的生产方式已经无法满足客户的需求。为了提高生产效率和产品质量,公司决定引进自动化生产线。

在自动化生产线的建设过程中,博众电气投入了大量的人力和物力资源。公司引进了先进的自动化组装设备和检测设备,实现了产线90%以上的自动化生产。这不仅大大提高了生产效率,还降低了人力成本,使得博众电气在市场竞争中更具优势。

C.K Magma公司的发展小趣事

在追求经济效益的同时,C.K Magma公司也积极履行社会责任。他们注重绿色发展和可持续经营,通过采用环保材料和工艺、优化生产过程等方式,降低产品对环境的影响。此外,公司还积极参与公益事业,为社会做出贡献。这些举措不仅提升了公司的社会形象,也为公司的长远发展提供了有力保障。

这五个故事展示了C.K Magma公司在电子行业中的发展历程和取得的成就。通过技术突破、市场拓展、国际合作、创新产品和绿色发展等方面的努力,公司逐渐在行业中崭露头角,成为了一家具有影响力和竞争力的企业。

E-San Electronic Co Ltd公司的发展小趣事

E-San Electronic Co Ltd的创始人李明,在电子科技行业摸爬滚打多年后,决定创立自己的公司。创业初期,公司面临着资金短缺、技术瓶颈和市场竞争激烈的挑战。李明凭借对电子技术的深刻理解和敏锐的市场洞察力,带领团队成功研发出了一款具有创新性的电子产品,并成功打入市场。这款产品以其高性价比和稳定的性能赢得了消费者的青睐,为公司带来了第一笔可观的收入,也为后续的发展奠定了坚实的基础。

Accuride公司的发展小趣事

Accuride公司在市场拓展方面也取得了显著成果。其产品不仅供应给北美地区的商用车制造商,还远销至其他国家。同时,Accuride与多家知名汽车品牌建立了紧密的合作关系,如Freightliner、Peterbilt、International、Great Dane和Mack等,为其提供高品质的零部件。这些合作伙伴关系的建立,不仅提升了Accuride的市场地位,也为其带来了稳定的订单和收入来源。

Anytek Technology Corporation Ltd公司的发展小趣事

Anytek始终坚持以创新为驱动,不断推出具有市场竞争力的新产品。2007年,公司自主研发的创新型产品“高清汽车行车记录仪”面世,这款产品以其高清画质、稳定性能和易用性等特点,迅速占领了市场制高点。随后,Anytek又于2008年推出了行业唯一一款双镜头的“双镜头行车记录仪”,这一创新设计进一步提升了行车记录仪的功能性和实用性,赢得了市场的广泛认可。

问答坊 | AI 解惑

关于题C的问题

本帖最后由 paulhyde 于 2014-9-15 09:30 编辑 AD603产生的自激现象严重,当用两级放大时候,第二级放大严重失真,这个是什么原因啊?我们现在在AD603前面加了OPA658做前级跟随器,希望可以减小自激  …

查看全部问答>

发个我用的元件库

这是我平常所用到的元件库…

查看全部问答>

wince 的cab 安装包问题(vs2005)

想做一个cab安装包,安装今日插件,按照网上的说明写了个安装程序setupdll.dll, 但是在模拟器上(pocket pc se 2003 Emulator)安装发现setupdll没有被调用(在函数Install_Exit中加了MessageBox,没有弹出,注册表也没写) cab安装包使用vs2005做的 ...…

查看全部问答>

GPRS连接问题

我用OPEN AT 已经建立完成了GPRS激活部分,但是为什么数据流中什么都收不到,在超级终端里使用ATD*99***1#,可以收到PPP包,如何使用OPEN AT ADL也能收到这些PPP包?请指教一二!我在软件里已经加入了AT命令,但是没有任何反应,到底是什么地方出了 ...…

查看全部问答>

用KernelIoControl获取逻辑中断号失败

我想使用EINTT4作按键中断输入.定义如下: UINT32  g_EINTIrq = IRQ_EINT4; UINT32  g_EINTSysIntr = SYSINTR_UNDEFINED; PUBLIC DWORD CPK_Init(DWORD dwContext) {             &n ...…

查看全部问答>

EVC4.0中窗体最小化问题

想要实现一个最小化功能 使用ShowWindow函数没反应~ 请问各位还有什么其他办法不?…

查看全部问答>

dshow CreateMediaType FreeMediaType 无法解析的外部符号

我在wince6.0上做dshow开发,已经包含的头文件和库 #include #include #include #include #include                                     &n ...…

查看全部问答>

CE6及BSP安装求救!!!!紧急啊

我之前安装开发环境的时候,发现PB中Device Driver中的SD选项没有,后来把Updates全装上了,就出现了SD选项。 前几天系统崩溃了,重新装上所有东西后发现就是SD选项没有,各位有没有遇到过这种情况啊????急 …

查看全部问答>

请教中断问题

我在做关于MPC8260的工作.目前,我想为DMA加入中断处理程序.MPC8260的参考手册中 说,IDMA1的中断号是6,我使用如下函数: intConnect(INUM_TO_IVEC(6),dma_isr,0); 连接中断处理程序与中断源.但是一旦DMA结束,BC中断到来之后,整个EP8260板子就死掉 ...…

查看全部问答>

MCS-51单片机定时器问题

MCS-51单片机中,采用12Mhz时钟,定时器T0采用模式1(16位计数器),请问在下面程序中,p1.0的输出频率 ? MOV TMOD,#01H SETB TR0 LOOP:MOV TH0,#0B1H MOV TL0,#0E0H LOOP1:JNB TF0,LOOP1 CLR TR0 CPL P1.0 SJMP LOOP…

查看全部问答>