移植modbus rtu主机到STM32

近期看了硬石电子的关于modbus rtu部分的代码,其中包括主机从机,这里记录主机如何使用,做一下笔记,方便以后查看。
移植modbus rtu主机到STM32_第1张图片

一、移植步骤

一共需要移植
三个.c文件:bsp_usartx_fifo.c、modbus_slave.c、bsp_SysTick.c
三个.h文件:bsp_usartx_fifo.h、modbus_slave.h、bsp_SysTick.h

放置三个函数:Usart_FIFO_Init(); SysTick_Init(); MODH_Poll();

开启三个宏:#define USART1_FIFO_EN 1//使能初始化串口1
__________ #define USART_SELECT_NUM 1//将modbus用在串口1
__________ #define HBAUD485 USART1_BAUD//设置串口波特率

1、串口初始化、定时器初始化、定时器初始化

(1)将Usart_FIFO_Init()放在主函数的初始化位置,

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_usartx_fifo.h"
#include "modbus_slave.h"
/*主函数*/
int main(void)
{
     
	Usart_FIFO_Init();
  	SysTick_Init();
	while ( 1 )
	{
     	 		
		MODH_Poll();
		TestModbusHost(1);//用于测试向从机发送数据,正式使用有用户编写
	}
}

(2)进入Usart_FIFO_Init(),看看有哪些需要初始化:

void Usart_FIFO_Init(void)
{
       
  /* 初始化串口相关的变量 */
  UsartVarInit();
  RS485_InitTXEN();
  /* 配置NVIC,设定USART接收中断优先级 */
  NVIC_Configuration_USART();
  
  /* 初始化USART对应GPIO和USART外设 */
  InitHardUsart();  
	/* 定时器初始化 */
  bsp_InitHardTimer();
}

a.首先UsartVarInit()的作用是对串口相关的结构体变量初始化,其中需要注意的是宏定义USART1_FIFO_EN的开关,这里我使用UART1做的测试,将该宏置1来开启串口1,然后#define USART_SELECT_NUM 1//将modbus用在串口1上;这里分为两部分,为的是方便对每个串口的单独配置,可以对其他串口添加需要的应用代码。

static void UsartVarInit(void)
{
     
#if USART1_FIFO_EN == 1
	g_tUsart1.usart = USART1;						/* STM32 串口设备 */
	g_tUsart1.pTxBuf = g_TxBuf1;					/* 发送缓冲区指针 */
	g_tUsart1.pRxBuf = g_RxBuf1;					/* 接收缓冲区指针 */
	g_tUsart1.usTxBufSize = USART1_TX_BUF_SIZE;	    /* 发送缓冲区大小 */
	g_tUsart1.usRxBufSize = USART1_RX_BUF_SIZE;	    /* 接收缓冲区大小 */
	g_tUsart1.usTxWrite = 0;			          	/* 发送FIFO写索引 */
	g_tUsart1.usTxRead = 0;						    /* 发送FIFO读索引 */
	g_tUsart1.usRxWrite = 0;						/* 接收FIFO写索引 */
	g_tUsart1.usRxRead = 0;						    /* 接收FIFO读索引 */
	g_tUsart1.usRxCount = 0;						/* 接收到的新数据个数 */
	g_tUsart1.usTxCount = 0;						/* 待发送的数据个数 */
	g_tUsart1.SendBefor = RS485_SendBefor;			/* 发送数据前的回调函数 */
	g_tUsart1.SendOver = RS485_SendOver;			/* 发送完毕后的回调函数 */
	g_tUsart1.ReciveNew = RS485_ReciveNew;			/* 接收到新数据后的回调函数 */
#endif
...
}

b.其次是对串口驱动的配置,初始化了485的引脚,配置中断优先级,配置串口引脚波特率等。
RS485_InitTXEN();
NVIC_Configuration_USART();
InitHardUsart();
c.为简化文件的个数,没有建立tim.c,直接将定时器初始化放在了串口初始化的末尾处bsp_InitHardTimer()。分频系数72-1,时钟周期1us。
(2)初始化SysTick_Init();主要用来统计主机发送完数据后的超时时间。

2、轮循MODS_Poll()

将MODH_Poll()放在主函数的while(1)中,用于接收来自从机的返回数据,其实直接放在用户的应用函数中就行,向从机发完数据,记录当前滴答定时器的时间,然后等待100ms,这期间就不断轮循这个函数即可,实例跳进测试函数TestModbusHost()即可查看到。

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_usartx_fifo.h"
#include "modbus_slave.h"
/*主函数*/
int main(void)
{
     
	Usart_FIFO_Init();
  	SysTick_Init();
	while ( 1 )
	{
     	 		
		MODH_Poll();
		TestModbusHost(1);//用于测试向从机发送数据,正式使用有用户编写
	}
}

3、添加寄存器

主机发送完指令后,从机会根据指令进行数据的返回,相应的就需要把这些数据存放进寄存器

void MODH_Read_03H(void)
{
     
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{
     
		bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */				
		switch (g_tModH.Reg03H)
		{
     
			case REG_P01:
//				if (bytes == 32)
//				{
     
					p = &g_tModH.RxBuf[3];	
					
					g_tVar.P01 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					g_tVar.P02 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
		
					g_tModH.fAck03H = 1;
//				}
				break;
		}
	}
}

二、代码及软件工具

链接:https://pan.baidu.com/s/1ZQqOA9Tqkr1qbF2bHohxSg
提取码:s4p7

你可能感兴趣的:(stm32,modbus,rtu主机移植stm32)