最近用到free modbus,需要在stm32上进行移植,以作modbus-RTU之用。现成协议的东西用起来很方便,现成源码很快就可以为设计者所用,也是当初制定标准的初衷吧。
首先下载最新的modbus源码,所谓技术更新换代的比较快,用就用最新的东西,协议嘛也要下载最新的,google一下,在http://www.freemodbus.org/index.php?idx=5下载最新的版本freemodbus-v1.5,下载最新的协议不仅可以防止被人改动导致自己做无用功,保持原生态也可以很好的与制定者进行交流。
解压freemodbus-v1.5,目录结构很清晰,主要有四个文件件,分别是demo、modbus、tools、doc。其中tools为上位机测试modbus程序,doc为一些说明文件先不讨论。有用的是demo以及modbus。打开demo,没有看到stm32的工程文件,有一个叫BARE的文件夹,是一些不包括任何处理器的部分源代码,我们就用这个建立工程文件。为了给以后移植modbus-TCP带来方便,这里直接打开之前测试好的基于ENC28J68的LwIP的stm32工程,在其中导入各个文件。
导入前的原始以太网测试工程
将prot以及modbus文件夹拷贝到工程文件夹下,导入工程,将demo中的main等几个函数拷贝到原先main.c中,注释掉原先的mian函数,就成了这个样子:
先理清所有依赖关系,肯定出现一大堆找不到头文件宏定义什么的错误,这个在keil中将文件夹的路径添加到include path中即可,非常方便。rebuild一下,发现有两个错误:
原来Keil4不支持inline这个关键字,直接将其删掉,编译出现了:
..\Output\STM32-DEMO.axf: Error:L6218E: Undefined symbol __aeabi_assert (referred from mbascii.o).出现的这个问题,各种百度以及谷歌,找了半天也没找到解决方法。这里不得不说百度虽然本土化做得很好,可是以英文作为关键词时,往往搜出一大堆不相干的东西,基本上搜不到国外的网页;谷歌本土化做的不好,服务器响应比较慢。想起360新出了搜索引擎,赶紧去试试,还真的有惊喜,在一篇帖子中写道“MicroLib并不支援assert(),所以才会出现错误讯息”,原来原工程使用了微库,在target中钩掉USE MicroLIB编译就可以通过了。昨天看优库老友记采访周鸿祎说360做搜索引擎,作为360的忠实用户应该支持一下。任何一个公司想做的更好,必须注意用户体验。
下面开始正式的移植以及分析和测试工作:
一、对于时钟的移植
由于modbus RTU模式需要定时器的支持,所以第一步先移植与定时器相关的函数。
在porttimer.c中添加BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )的实现,实现50us的基时时钟。
添加打开和关闭时钟的函数void vMBPortTimersEnable( )以及voidvMBPortTimersDisable( ),还有超时中断函数voidTIM4_IRQHandler(void)。
二、对串口通信的移植
无论是modbus ASCII还是RTU模式,都以串口通讯做为载体,需要添加串口的使能BOOL
xMBPortSerialInit,收发中断的使能voidvMBPortSerialEnable( BOOLxRxEnable, BOOL xTxEnable ),发送以及接收BOOL xMBPortSerialPutByte( CHAR ucByte ),BOOL
xMBPortSerialGetByte( CHAR * pucByte ),这几个函数没什么好说的,有两个中断函数我比较好奇,就是static void prvvUARTTxReadyISR( void )以及staticvoid prvvUARTRxISR( void ),就是一个发送中断一个接收中断,为什么是这样的名字呢,stm32串口发生中断怎么去调用它们呢,如果换成其他单片机,为什么是这样的一个名字呢?原来在freemodbus中并没有提供中断函数的具体名称,还需要根据自己使用的处理器自己添加中断处理函数voidUSART1_IRQHandler(void),在其中调用上述两个发送和接收的函数。
三、第一个功能单元——读写寄存的支持
FreeModbus源码包中BARE工程文件的main.c中定义了
eMBErrorCode eMBRegInputCB()、eMBErrorCode eMBRegHoldingCB()