当前位置:首页 > 单片机 > 单片机
[导读]这几天因为工作需要,移植了modbus RTU到STM32来,之前也听说过modbus,但是没有深入了解过,还以为会像usb 那样复杂的,经过这几天的折腾,发现真的太简单了。为了防止过段时间又忘记了怎么移植,在这里把移植过程记

 

这几天因为工作需要,移植了modbus RTU到STM32来,之前也听说过modbus,但是没有深入了解过,还以为会像usb 那样复杂的,经过这几天的折腾,发现真的太简单了。为了防止过段时间又忘记了怎么移植,在这里把移植过程记录下来,也为了方便初次接触modbus的人。

废话少说,首先去下载源码,我下载的是freemodbus-v1.5.0,解压后如图所示:

在demo文件夹中有很多移植好的例子,但是没有STM32的,不要紧,我们参考已有的例子来操作就可以了。在demo文件夹下新建一个文件夹,命名为STM32,将BARE文件夹里的文件全部复制过来。
然后,我们建立一个STM32的工程,我用的是mdk4.72,关于怎么建立工程我就不啰嗦了,在工程里添加modbus 和 port两个文件夹,并在文件夹里添加需要的文件,这些modbus的是在modbus文件夹下面,port的是在刚才新建的那个stm32文件夹下,port.c是我从别的地方弄过来的,里面就是一个开中断和一个关中断的函数,可以不要,我的工程如图:

乍一看,也有十几个文件,其实这些文件内容不多,很好理解,而且需要修改的只有port文件夹下的portserial.c 和 porttimer.c 。这两个文件里面有几个空函数,我们看名字就知道这些函数的作用了。
portserial.c如下:

[C]纯文本查看复制代码

?

010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263#include "port.h"/* ----------------------- Modbus includes ----------------------------------*/#include "mb.h"#include "mbport.h"/* ----------------------- static functions ---------------------------------*/staticvoidprvvUARTTxReadyISR(void);staticvoidprvvUARTRxISR(void);/* ----------------------- Start implementation -----------------------------*/voidvMBPortSerialEnable(BOOLxRxEnable,BOOLxTxEnable ){/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/}BOOLxMBPortSerialInit(UCHARucPORT,ULONGulBaudRate,UCHARucDataBits, eMBParity eParity ){returnFALSE;}BOOLxMBPortSerialPutByte(CHARucByte ){/* Put a byte in the UARTs transmit buffer. This function is called* by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been* called. */returnTRUE;}BOOLxMBPortSerialGetByte(CHAR* pucByte ){/* Return the byte in the UARTs receive buffer. This function is called* by the protocol stack after pxMBFrameCBByteReceived( ) has been called.*/returnTRUE;}/* Create an interrupt handler for the transmit buffer empty interrupt* (or an equivalent) for your target processor. This function should then* call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that* a new character can be sent. The protocol stack will then call* xMBPortSerialPutByte( ) to send the character.*/staticvoidprvvUARTTxReadyISR(void){pxMBFrameCBTransmitterEmpty( );}/* Create an interrupt handler for the receive interrupt for your target* processor. This function should then call pxMBFrameCBByteReceived( ). The* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the* character.*/staticvoidprvvUARTRxISR(void){pxMBFrameCBByteReceived( );}

根据注释,可以知道vMBPortSerialEnable是串口发送和接收中断的控制的,包括发送中断和接收中断,在这里,我们用的是RXNE 和 TXE中断,代码如下:

[C]纯文本查看复制代码

?

0102030405060708091011121314151617181920voidvMBPortSerialEnable(BOOLxRxEnable,BOOLxTxEnable ){if(TRUE==xRxEnable){USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);}else{USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);}if(TRUE==xTxEnable){USART_ITConfig(USART1, USART_IT_TXE, ENABLE);}else{USART_ITConfig(USART1, USART_IT_TXE, DISABLE);}}

而xMBPortSerialInit函数显然是串口初始化的了,因为我在usart.c已经有一个串口初始化函数,这里直接调用该初始化函数usart_init(ulBaudRate);同时将return FALSE 改成 return TRUE; 注意这里我们只用了波特率这个参数,其他参数直接忽略,你也可以根据自己需要改一下。
然后xMBPortSerialPutByte 和xMBPortSerialGetByte 分别是发送和接收一个字节数据的函数,这里我直接调用库函数;

[C]纯文本查看复制代码

?

0102030405060708091011121314151617BOOLxMBPortSerialPutByte(CHARucByte ){USART_SendData(USART1, ucByte);while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)/*????·????ê??*/{}returnTRUE;}BOOLxMBPortSerialGetByte(CHAR* pucByte ){*pucByte = USART_ReceiveData(USART1);returnTRUE;}

最后还有两个中断处理函数,把前面的static 去掉,因为我不想把我的串口中断函数放到这个文件。然后我们在stm32f10x_it.c添加串口中断函数,如下:

[C]纯文本查看复制代码

?

0102030405060708091011121314voidUSART1_IRQHandler(void){if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET){prvvUARTRxISR();USART_ClearITPendingBit(USART1, USART_IT_RXNE);}if(USART_GetITStatus(USART1, USART_IT_TXE) == SET){prvvUARTTxReadyISR();// USART_ClearITPendingBit(USART1, USART_IT_TXE);}}

至此,portserial.c处理完毕。
porttimer.c的移植和portserial.c十分相似,但是要特别注意定时器中断的时间长度应该是3.5个字符时间,我这里只是简单粗暴的按照波特率是9600时候计算的。文件很短,直接上代码

[C]纯文本查看复制代码

?

01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849BOOLxMBPortTimersInit(USHORTusTim1Timerout50us ){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_DeInit(TIM2);#if 0TIM_TimeBaseStructure.TIM_Period = 0x7E54;//CLK==24MHz ((1000000000/9600)*11*3.5)/(1000/24) == 0x7e54TIM_TimeBaseStructure.TIM_Prescaler = 0x3;#endif// ?????????¤·?????????7200/72M = 0.0001,????100us????????1//10us x 50 = 5ms,??5ms????????TIM_TimeBaseStructure.TIM_Period = 50;TIM_TimeBaseStructure.TIM_Prescaler = (7200 - 1);TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, ENABLE);returnTRUE;}voidvMBPortTimersEnable( ){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);TIM_SetCounter(TIM2, 0);//TIM_Cmd(TIM2, ENABLE);TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);}voidvMBPortTimersDisable( ){TIM_SetCounter(TIM2, 0);//TIM_Cmd(TIM2, DISABLE);TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);}voidTIMERExpiredISR(void){(void)pxMBPortCBTimerExpired();}

同样,在stm32f10x_it.c添加定时器中断处理函数,

[C]纯文本查看复制代码

?

12345voidTIM2_IRQHandler(void){TIMERExpiredISR();TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}


然后,我们还需要自己写四个回调函数,分别是读输入寄存器函数、读写保持寄存器函数、读写线圈函数和读离散寄存器函数,一般只用读写保持寄存器函数即可,具体怎么实现可以参考demo文件夹里面众多的demo.c文件。

 

 

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

STM32与51单片机之间有什么差异呢?两者可以说是一场科技与性能的较量了。在科技飞速发展的今天,微控制器(MCU)已广泛应用于各类电子设备和系统中,发挥着举足轻重的作用。其中,STM32和51单片机作为两种常见的微控制...

关键字: STM32 51单片机 MCU

电磁铁是一种利用电流产生磁场的装置,具有快速响应、易于控制等特点,在工业自动化、电子设备、科学实验等领域有着广泛的应用。STM32是一款功能强大的微控制器,具有高性能、低功耗、易于编程等优点,是控制电磁铁的理想选择。本文...

关键字: 电磁铁 微控制器 STM32

边缘人工智能的实现涉及到三个基本 要素:安全性,连接性、自主性,而其中自主性是AI能力的体现,也是边缘AI有别于其他传统的物联网的关键。而通过ST Edge AI套件,就可以帮助各种不同类型的开发者实现覆盖全硬件平台的全...

关键字: 边缘人工智能 AI STM32

今天,小编将在这篇文章中为大家带来STM32单片机最小系统的有关报道,通过阅读这篇文章,大家可以对它具备清晰的认识,主要内容如下。

关键字: 单片机 单片机最小系统 STM32

STM32是一款由STMicroelectronics生产的微控制器系列,具有高性能、低功耗和丰富的外设资源。其中,串口通信是一种常用的通信方式,可以实现与其他设备之间的数据传输。

关键字: STM32 串口通信 微控制器

STM32是一种广泛使用的微控制器,具有丰富的通信接口。其中,串口通信是STM32与其他设备或系统进行数据交换的重要方式之一。本文将详细介绍STM32串口通信的原理、应用及常见故障。

关键字: STM32 串口通信

由于目前缺乏相应的监测技术,地下电缆线路出现异常运行状态无法被及时发现,久而久之易演变成大故障,最终只能通过更换地下电缆进行修复,耗费大量的人力、物力。鉴于此,开发了一种基于STM32的地下电缆异常状态检测系统,利用热传...

关键字: STM32 地下电缆

交通灯控制器是用于控制交通信号灯运行的设备,它可以根据交通流量、行人需求以及其他因素,动态地调整信号灯的变化时间和绿灯时长,以保证交通的流畅和安全。

关键字: 交通信号灯 STM32
关闭
关闭