ModBus--RTU学习心得(含MB从机stm32工程)


ModBus入门学习篇(含MB-RTU从机stm32工程)


Modbus是一种比较常用的工业通讯协议(协议也可以称为约定),它对传输介质的要求并不高,基本上可用实现通讯链接就可以(rs232、rs485、网线等电器通讯均可),这可能也是它比较常用的原因之一,重要的是这个协议它是免费的而且也是一个普遍认可的协议,所有学习一下还是有必要的。
学习modbus(以下简称MB)之前需要搞清楚一个概念“协议”,协议到底是什么呢?
说到协议一般来说大家应该都听说过TCP/IP这个网络协议,tcp/ip是一个大型网络协议相对来说是比较复杂的,但是并不代表协议就是一个复杂的东西。
协议其实就是一种约定。
例如:甲方跟乙方约定好,当乙方接到甲方的信息aa时,乙方给甲方寄出一个东西并回复一个信息bb,这就是协议的模型,协议就是双方都能按照规定来进行交流和执行。
下面以单片机通讯做一简单的协议
协议:1、规定数据格式: 帧头-0x3e 地址 指令 数据 帧尾-0x3f,这个是通讯双方的通讯数据包格式。
2、规定功能指令:A–控制电机正转 B–控制电机反转 C–电机停止转动。
当单片机接收到数据:0x3e 0x01 A 03 0x3f 根据以上规定的协议,接收到这帧数据之后单片机将会执行正转3圈的动作,这就是一个简单的协议。

对协议有一个初步的理解之后,再看看modbus协议。
一、Modbus简介
Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。

此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

当在一Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。
 
ModBus是一种主从问询式的通讯方式,由主机(或者client)发起询问从机接收到问询之后响应主机服务。
ModBus--RTU学习心得(含MB从机stm32工程)
二、传输方式与数据帧格式
MB有两种传输模式:ASCII或RTU
ASCII消息帧格式
使用ASCII模式,消息以冒号(:)字符(ASCII码 3AH)开始,以回车换行符结束(ASCII码 0DH,0AH)。
ModBus--RTU学习心得(含MB从机stm32工程)
ModBus--RTU学习心得(含MB从机stm32工程)RTU消息帧格式
ModBus--RTU学习心得(含MB从机stm32工程)ModBus--RTU学习心得(含MB从机stm32工程)
这两个传输模式的区别:
1、数据帧的格式不同,ASCII模式下有帧头、帧尾而RTU模式下是没有帧头和帧尾的,RTU模式下数据帧的第一个数据就是地址。
2、数据校验的方式不一样,ASCII模式使用的是LRC校验 ,RTU使用的是crc校验
3、数据的表示方式不同,ASCII使用一个ASCII字符表示一位十六进制数,RTU模式下是用4bit二进制表示一位16进制数,因此RTU模式的数据帧长度是要小于ASCII模式的,所有RTU模式的传输速率大于ASCII模式。

以上是关于modbus协议的一个简介,详细介绍网上很多这里就不多讲了,具体内容了解可以看Modbus协议中文版(GB),和Modbus协议详解这个博客。


STM32-modbus rtu 从机程序


modbu功能处理c文件

#include "modbus.h"
#include "usart.h"
#include "modbus_timer.h"
#include "modbus_crc.h"

MODBUS modbus;


u16 DataReg[30] ={0}; //¶¨Òå30¸ö16λµÄ¼Ä´æÆ÷
u8 OX[20];			//¶¨ÒåÊä³öÏßȦ±äÁ¿


void modbus_err_response(u8 cmd, u8 err)
{
	u16 crc;
	u8 i=0;
	modbus.tx_buf[i++] = modbus.local_addr;//±¾»úµØÖ·
	modbus.tx_buf[i++] = cmd|0x80;        //·µ»Ø¹¦ÄÜÂë=¹¦ÄÜÂë+0x80
	modbus.tx_buf[i++] = err;
	crc = Modbus_CRC16(modbus.tx_buf,i);    //¼ÆËãCRC
	modbus.tx_buf[i++] = crc/256;
	modbus.tx_buf[i++] = crc%256;
	Modbus_Uart_Send(modbus.tx_buf,i);
}



// Modbus³õʼ»¯º¯Êý
void Modbus_Init(void)
{
	u8 i;
	modbus.local_addr = 0x01; //É豸µØַΪ0x01
	modbus.rx_flag = 0;
	Modbus_Uart_Init(9600);
	Modbus_TIM_Init();
	for(i=0;i<30;i++) DataReg[i]=i;
	for(i=0;i<20;i++) OX[i]=i;
}


//Modbus 1ºÅ¹¦ÄÜÂ뺯Êý£¬¶ÁÏßȦ״̬
void Modbus_Fun1(void)
{
	u16 ox_addr,ox_cnt,crc;
	u8 i,j;
	
	ox_addr = modbus.rx_buf[2]*256+modbus.rx_buf[3];
	ox_cnt =  modbus.rx_buf[4]*256+modbus.rx_buf[5];
	
	if(ox_cnt<1 || ox_cnt>0x7d0)		//ÅжÏÏßȦ¸öÊýÊÇ·ñÔڹ涨ÇøÓòÄÚ£¬Èç¹û²»ÔÚ·¶Î§ÄÚÔò·µ»ØÒì³£3
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_2);
		return;
	}
	
	if( ox_addr>1600)
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_3);
		return;
	}
	
	i=0;
	modbus.tx_buf[i++] = modbus.local_addr;      //·¢Ëͱ¾»úµØÖ·
	modbus.tx_buf[i++] = 0x01;              //¹¦ÄÜÂë
	
	if(ox_cnt%8 != 0)  //Åж϶ÁÈ¡ÏßȦ¸öÊýÊÇ·ñÊÇ8µÄÕûÊý±¶£¬Èç¹û²»ÊÇ8µÄÕûÊý±¶Ôò·µ»Øox_cnt/8+1¸ö×Ö½ÚÊý¾Ý
	{
		modbus.tx_buf[i++] = (u8)(ox_cnt/8)+1;  //·µ»Øox_cnt/8+1×Ö½ÚÊý¾Ý
		if(ox_addr%8)          //ÅжϵØÖ·ÊÇ·ñÊÇ8µÄÕûÊý±¶£¬Ò»¸öu8µÄ±äÁ¿´æ´¢8¸öÏßȦµÄ¿ª¹ØÖµ£¬Èç¹û²»ÊÇÕûÊý±¶ÔòÐèÒªÒÆλÀ´½øÐÐλѰַ
		{
			for(j=0;j<ox_cnt/8;j++)
			{
				modbus.tx_buf[i++]=(OX[ox_addr/8+j]>>(ox_addr%8))|(OX[ox_addr/8+j+1]<<(8-ox_addr%8));   //¶ÁÈ¡ÏßȦ¿ª¹ØÖµ
			}
			modbus.tx_buf[i++]=((OX[ox_addr/8+j]>>(ox_addr%8))|(OX[ox_addr/8+j+1]<<(8-ox_addr%8)))&(0xff>>(8-ox_cnt%8));
		}
		else     //ÈôÊÇÕûÊý±¶Ôò°´×Ö½ÚÑ°Ö·¼È¿É£¬´ÓOX[20]ÖжÁÈ¡Õû¸ö±äÁ¿·µ»Ø¼´¿É
		{
			for(j=0;j<(ox_cnt/8);j++)
			{
				modbus.tx_buf[i++]=OX[ox_addr/8+j];
			}
			modbus.tx_buf[i++] = OX[ox_addr/8+j] & (0xff>>(8-ox_cnt%8));
		}
	}
	else          //¶ÁÈ¡¸öÊýÕýºÃÊÇ8µÄÕûÊý±¶Ôò·µ»Øox_cnt/8¸ö×Ö½ÚµÄÊý¾Ý
	{
		modbus.tx_buf[i++] = ox_cnt/8;
		if(ox_addr%8 != 0)
		{
			for(j=0;j<ox_cnt/8;j++)
			{
				modbus.tx_buf[i++]=(OX[ox_addr/8+j]>>(ox_addr%8))|(OX[ox_addr/8+j+1]<<(8-ox_addr%8));
			}
		}
		else
		{
			for(j=0;j<(ox_cnt/8);j++)
			{
				modbus.tx_buf[i++]=OX[ox_addr/8+j];
			}
		}
	}
	
	crc = Modbus_CRC16(modbus.tx_buf,i);    //¼ÆËãCRC
	modbus.tx_buf[i++] = crc/256;
	modbus.tx_buf[i++] = crc%256;
	
	Modbus_Uart_Send(modbus.tx_buf,i);
}
 




// Modbus 3ºÅ¹¦ÄÜÂ뺯Êý£¬¶Á¼Ä´æÆ÷Êý¾Ý
void Modbus_Func3()
{
	u16 Reg_addr,Reg_cnt,crc;
	u8 i,j;	
	
	Reg_addr = modbus.rx_buf[2]*256+modbus.rx_buf[3];//»ñÈ¡±»¶Á¼Ä´æÆ÷µÄµØÖ·
	Reg_cnt = modbus.rx_buf[4]*256+modbus.rx_buf[5];//»ñÈ¡¶ÁÈ¡¼Ä´æÆ÷µÄ¸öÊý
	
	if(Reg_cnt<1 || Reg_cnt>0x7d0)		//ÅжÏÏßȦ¸öÊýÊÇ·ñÔڹ涨ÇøÓòÄÚ£¬Èç¹û²»ÔÚ·¶Î§ÄÚÔò·µ»ØÒì³£3
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_3);
		return;
	}
	
	if(Reg_addr>30)			//Òì³£Åжϣ¬Èô¼Ä´æÆ÷µØÖ·²»ºÏ·¨Ôò·µ»ØÒì³£2
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_2);
		return;
	}
	
	
	//·µ»ØÓ¦´ðÊý¾Ý°ü
	i = 0;
	modbus.tx_buf[i++] = modbus.local_addr;      //·¢Ëͱ¾»úµØÖ·
	modbus.tx_buf[i++] = 0x03;              //¹¦ÄÜÂð
	modbus.tx_buf[i++] = ((Reg_cnt*2)%256);   //·µ»ØÊý¾Ý³¤¶È
	
	for(j=0;j<Reg_cnt;j++)                    //·µ»ØÊý¾Ý
	{
		modbus.tx_buf[i++] = DataReg[Reg_addr+j]/256;
		modbus.tx_buf[i++] = DataReg[Reg_addr+j]%256;
	}
	
	crc = Modbus_CRC16(modbus.tx_buf,i);    //¼ÆËãCRC
	modbus.tx_buf[i++] = crc/256;
	modbus.tx_buf[i++] = crc%256;
	// ·¢ËÍÊý¾Ý


	Modbus_Uart_Send(modbus.tx_buf,i);

}

void Modbus_Func5(void)
{
	u16 ox_addr,val,crc;
	u8 i=0;
	
	ox_addr = modbus.rx_buf[2]*256+modbus.rx_buf[3]; //µØÖ·
	val=modbus.rx_buf[4]*256+modbus.rx_buf[5];     //дÈëÖµ£¬0xff00ÏßȦдON,0x0000ÏßȦдÈëOFF
	
	if(val != 0 && val != 0xff00)		//ÅжÏÏßȦ¸öÊýÊÇ·ñÔڹ涨ÇøÓòÄÚ£¬Èç¹û²»ÔÚ·¶Î§ÄÚÔò·µ»ØÒì³£3
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_3);
		return;
	}
	
	if(ox_addr> 1600)
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_2);
		return;
	}
	
	if(val == 0xff00)
		OX[ox_addr/8] |= 1<<(ox_addr%8);
	else
		OX[ox_addr/8] &= ~(1<<(ox_addr%8));
	
	//ÏìÓ¦
	modbus.tx_buf[i++]=modbus.local_addr;//±¾»úµØÖ·
	modbus.tx_buf[i++]=0x05;        //¹¦ÄÜÂë 
	modbus.tx_buf[i++]=ox_addr/256;
	modbus.tx_buf[i++]=ox_addr%256;
	
	modbus.tx_buf[i++]=val/256;
	modbus.tx_buf[i++]=val%256;
	crc=Modbus_CRC16(modbus.tx_buf,i);
	modbus.tx_buf[i++]=crc/256;  
	modbus.tx_buf[i++]=crc%256;
	
	Modbus_Uart_Send(modbus.tx_buf,i); //ÏòÖ÷»ú·¢ËÍÊý¾Ý
	
}




// Modbus 6ºÅ¹¦Äܺ¯Êý£¬Ö÷»úдÈë¼Ä´æÆ÷Öµ
void Modbus_Func6()  
{
	u16 Reg_addr,val,crc;
	u8 i=0;
	Reg_addr=modbus.rx_buf[2]*256+modbus.rx_buf[3];  //»ñÈ¡±»Ð´¼Ä´æÆ÷µØÖ·
	val=modbus.rx_buf[4]*256+modbus.rx_buf[5];     //Ð޸ĺóµÄÖµ
	
	if(val>0xffff)		//ÅжÏÏßȦ¸öÊýÊÇ·ñÔڹ涨ÇøÓòÄÚ£¬Èç¹û²»ÔÚ·¶Î§ÄÚÔò·µ»ØÒì³£3
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_3);
		return;
	}
	
	if( Reg_addr> 30)
	{
		modbus_err_response(modbus.rx_buf[1],ERROR_2);
		return;
	}
	
	
	DataReg[Reg_addr]=val;  //Ð޸ı¾É豸¼Ä´æÆ÷Öµ
	
	//ÏìÓ¦Ö÷»ú
	modbus.tx_buf[i++]=modbus.local_addr;//±¾»úµØÖ·
	modbus.tx_buf[i++]=0x06;        //¹¦ÄÜÂë 
	modbus.tx_buf[i++]=Reg_addr/256;
	modbus.tx_buf[i++]=Reg_addr%256;
	
	modbus.tx_buf[i++]=val/256;
	modbus.tx_buf[i++]=val%256;
	crc=Modbus_CRC16(modbus.tx_buf,i);
	modbus.tx_buf[i++]=crc/256;  
	modbus.tx_buf[i++]=crc%256;
	
	Modbus_Uart_Send(modbus.tx_buf,i);
	
}




 
// Modbus´¦Àíº¯Êý
void Modbus_Msg_Handle()
{
	u16 crc,rccrc;
	u8 i;
	if(modbus.rx_flag == 0)  //ûÊÕµ½Êý¾Ý°ü
	{
	   return;
	}
	
	if(modbus.rx_buf[0] == modbus.local_addr)
	{
		crc = Modbus_CRC16(&modbus.rx_buf[0],modbus.rx_count-2); //¼ÆËãÊý¾Ý°üCRC
		rccrc = modbus.rx_buf[modbus.rx_count-2]*256+modbus.rx_buf[modbus.rx_count-1];//¶ÁÈ¡CRC
		if(crc == rccrc) 
		{
			if(modbus.rx_buf[1]<20)
			{
				switch(modbus.rx_buf[1])   //¸ù¾Ý¹¦ÄÜÂëÑ¡ÔñÖ´ÐгÌÐò
				{
					case 1: 
						Modbus_Fun1();       
						break;
					
					case 2: 
						break;
					
					case 3: 
						Modbus_Func3();    
						break;
					
					case 4:   
						break;
					
					case 5:  
						Modbus_Func5();    
						break;
					
					case 6: 
						Modbus_Func6();    
						break;
					
					case 7:     
						break;
					
					case 8:       
						break;
					
					case 9:      
						break;
					
					case 10:           
						break;	
					
					default:			
						break;
				}
			}
			//¹¦ÄÜÂ볬³ö¹æ¶¨·¶Î§·µ»ØÒì³£Âë01
			else 
			{
				modbus.tx_buf[i++] = modbus.local_addr;            //±¾»úµØÖ·
				modbus.tx_buf[i++] = modbus.rx_buf[1]|0x80;        //·µ»Ø¹¦ÄÜÂë=¹¦ÄÜÂë+0x80
				modbus.tx_buf[i++] = ERROR_1;
				Modbus_Uart_Send(modbus.tx_buf,i);
				return;
			}
		}
		
	}
	modbus.rx_count = 0;
	modbus.rx_flag = 0; 
}

modbus_crc.c文件


#include "modbus_crc.h"


u8 const auchCRCHi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};

u8 const auchCRCLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};



u16  Modbus_CRC16( u8 *puchMsg, u16 DataLen )
{
    u8 uchCRCHi = 0xFF ; //crc¸ß×Ö½Ú³õʼ»¯
    u8 uchCRCLo = 0xFF ; // CRCµÍ×Ö½Ú³õʼ»¯
    unsigned long uIndex ; 		// crcÑ­»·Ë÷Òý
 
    while ( DataLen-- ) 	// 
    {
        uIndex = uchCRCHi ^ *puchMsg++ ; 	// 
        uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
        uchCRCLo = auchCRCLo[uIndex] ;
    }
 
    return ( uchCRCHi << 8 | uchCRCLo ) ;
}

modbus_timer.c文件

#include "modbus_timer.h"
#include "sys.h"
#include "modbus.h"
#include "led.h"

void Modbus_TIM_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	RCC_APB1PeriphClockCmd(Modbus_Time_Clock , ENABLE);
	
	//¶¨Ê±Æ÷3²ÎÊýÅäÖÃ
	TIM_TimeBaseStructure.TIM_Period = Modbus_Time_arr;
	TIM_TimeBaseStructure.TIM_Prescaler = Modbus_Time_psc;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
	
	TIM_TimeBaseInit(Modbus_Timer, &TIM_TimeBaseStructure);
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);              //¶¨Ê±Æ÷3¸üÐÂÖжÏʹÄÜ

	//³õʼ»¯¶¨Ê±Æ÷3µÄÖжÏÏòÁ¿
	NVIC_InitStructure.NVIC_IRQChannel = Modbus_Time_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	    
	
	TIM_SetCounter(Modbus_Timer,0);
	TIM_Cmd(Modbus_Timer,DISABLE); 	//ʹÄܶ¨Ê±Æ÷3
	
}




void Modbus_TIM_IRQHandler(void)  
{
	if (TIM_GetITStatus(Modbus_Timer, TIM_IT_Update) != RESET) //²úÉúʼþÖжÏ
	{
		TIM_ClearITPendingBit(Modbus_Timer, TIM_IT_Update);  //Çå³ý¶¨Ê±Æ÷Öжϱê¼Ç
		
		modbus.rx_flag = 1;			//¼ä¸ô8msδ½ÓÊÕµ½Êý¾Ý±íʾһ֡Êý¾Ý½ÓÊÕÍê³É£¬½ÓÊÕÍê³É±ê¼ÇÖÃ1				
		TIM_Cmd(Modbus_Timer,DISABLE);    //¶¨Ê±Æ÷½ûÓÃ
		LED0 = !LED0;
	}
}

usart.c文件

#include "sys.h"
#include "usart.h"	  
#include "modbus.h" 
#include "modbus_timer.h"


#if 1
#pragma import(__use_no_semihosting)             
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ    
_sys_exit(int x) 
{ 
	x = x; 
} 
//Öض¨Òåfputcº¯Êý 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

void UART1_TX(u8 dat)
{
	while((USART1->SR&0X40)==0);
	USART1->DR = dat;
}

void Modbus_Uart_Send(u8 *dat ,u8 cnt)
{
	u8 i;
	for(i=0;i<cnt;i++)
	{
		UART1_TX(dat[i]);
	}
}
 
 
	  
  
void Modbus_Uart_Init(u32 bound)
{
  //GPIO¶Ë¿ÚÉèÖÃ
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//ʹÄÜUSART1£¬GPIOAʱÖÓ

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//¸´ÓÃÍÆÍìÊä³ö
	GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.9

	//USART1_RX	  GPIOA.10³õʼ»¯
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
	GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.10  

	//Usart1 NVIC ÅäÖÃ
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//ÇÀÕ¼ÓÅÏȼ¶1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//×ÓÓÅÏȼ¶0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷

	//USART ³õʼ»¯ÉèÖÃ

	USART_InitStructure.USART_BaudRate = bound;//´®¿Ú²¨ÌØÂÊ
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ
	USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//ÊÕ·¢Ä£Ê½

	USART_Init(USART1, &USART_InitStructure); //³õʼ»¯´®¿Ú1
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖжÏ
	USART_Cmd(USART1, ENABLE);                    //ʹÄÜ´®¿Ú1 

}

void USART1_IRQHandler(void)                	//´®¿Ú1ÖжϷþÎñ³ÌÐò
{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
	{
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);   //Çå³ý½ÓÊÕÖжϱêÖ¾
		Res =USART_ReceiveData(USART1);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
		
		
	    if( modbus.rx_flag==1)  
		{
		   return ;
		}

		TIM_SetCounter(Modbus_Timer,0);   //Çå³ý¶¨Ê±Æ÷¼ÆÊý
		TIM_Cmd(Modbus_Timer, ENABLE);   //¿ªÆô¶¨Ê±Æ÷
		
		modbus.rx_buf[modbus.rx_count++] = Res;
		
     } 
} 

实测可用:
modbus调试助手测试
ModBus--RTU学习心得(含MB从机stm32工程)modscan32测试:
1、读线圈:
ModBus--RTU学习心得(含MB从机stm32工程)2、读保持寄存器:
ModBus--RTU学习心得(含MB从机stm32工程)
以上几个.c文件基本上实现了modbus协议功能,但是注释复制过来之后显示有问题(应该是编码格式的问题),如果有需要的话可以下载源文件modbus资源,资源包里面有modbus协议RTU模式源代码(STM32keil工程文件)以及modbus调试助手、modbus协议详细文档(英文版)。

上一篇:Modbus CRC16 校验计算函数


下一篇:探讨NET Core数据进行3DES加密或解密弱密钥问题