Modbus向MSP430F149上的移植步骤FreeModbus的MSP430版本的demo是在GCC平台,现移植到IAR上,版本5.3。先说几点在GCC平台移植到IAR平台要改的几处地方1.先按照如图所示在IAR中建立好工程文件以及工程目录2.在system文件夹下建立DCO.C文件配置系统时钟,由于一般使用430单片机的外部8M晶振,因此此处我们自己写的函数只要和作者的留的接口对上即可。DCO.C文件代码如下:#include../port/port.h#includedco.h/*-----------------------Startimplementation-----------------------------*/charcTISetDCO(intdelta){charz,result;/*------选择主系统时钟为8MHZ-------*/BCSCTL1&=~XT2OFF;//打开XT2高频振荡器do{IFG1&=~OFIFG;//清除振荡器失效标志for(z=0xFF;z0;z--);//等待8MHZ晶振起振}while((IFG1&OFIFG));//判断晶振失效标志是否依然存在BCSCTL2|=SELM_2+SELS;//MCLK和SMCLK选择高频振荡器result=TI_DCO_NO_ERROR;return(result);}。前面说的与作者的留的接口对接,也就是返回值为char类型的TI_DCO_NO_ERROR即可。3.官方demo使用的MCU为MSP430F169,我用的开发板是F149因此要更改相应的库函数。文件port.h.更改为:/*-----------------------Platformincludes--------------------------------*/#includemsp430x14x.h#ifdefined(__GNUC__)#includesignal.h#endif#undefCHARPortserial.c中usOldSR=_DINT()程序,_DINT()是没有返回值的所以编译会报错,将该部分程序更改为这样文件:Portserial.c---EnterCriticalSection(void)更改为:voidEnterCriticalSection(void){USHORTusOldSR;if(ucCriticalNesting==0){#ifdefined(__GNUC__)usOldSR=READ_SR;_DINT();#else//usOldSR=_DINT();#endif//ucGIEWasEnabled=usOldSR&GIE?TRUE:FALSE;_DINT();ucGIEWasEnabled=TRUE;}ucCriticalNesting++;}文件:Portserial.c---ExitCriticalSection(void)更改为:voidExitCriticalSection(void){ucCriticalNesting--;if(ucCriticalNesting==0){if(ucGIEWasEnabled){ucGIEWasEnabled=FALSE;_EINT();}}}更改中断服务函数,原程序的中断服务函数格式不能在IAR中使用,因此要更改为IAR格式文件:portserial.c---prvvMBSerialRXIRQHandler(void)更改为:#pragmavector=USART0RX_VECTOR__interruptvoidprvvMBSerialRXIRQHandler(void)//__interrupt[USART0RX_VECTOR]{DEBUG_TOGGLE_RX();pxMBFrameCBByteReceived();}文件:portserial.c---prvvMBSerialTXIRQHandler(void)更改为:#pragmavector=USART0TX_VECTOR__interruptvoidprvvMBSerialTXIRQHandler(void)//__interrupt[USART0TX_VECTOR]{DEBUG_TOGGLE_TX();pxMBFrameCBTransmitterEmpty();}文件:porttimer.c---prvvMBTimerIRQHandler(void)更改为:#pragmavector=TIMERA0_VECTOR__interruptvoidprvvMBTimerIRQHandler(void){(void)pxMBPortCBTimerExpired();}main.c中有4个配置宏,REG_INPUT_START定义输入寄存器的开始地址,这里我配置成0;REG_INPUT_NREGS定义输入寄存器的数目,我配置为4个;REG_HOLDING_START定义保持寄存器的开始地址,这里我配置为0;REG_HOLDING_NREGS定义保持寄存器的个数,这里我定义为125。文件:main.c更改为:文件:main.c更改为:/*-----------------------Defines------------------------------------------*/#defineREG_INPUT_START0#defineREG_INPUT_NREGS4#defineREG_HOLDING_START0#defineREG_HOLDING_NREGS125这里配置modbus支持的工作模式,有RTU、ASCII、TCP三种模式。0表示失能,1表示使能。这里我只开启RTU模式,当然了你也可以选择都开启。文件:mbconfig.h更改为:/*!\briefIfModbusASCIIsupportisenabled.*/#defineMB_ASCII_ENABLED(0)/*!\briefIfModbusRTUsupportisenabled.*/#defineMB_RTU_ENABLED(1)/*!\briefIfModbusTCPsupportisenabled.*/#defineMB_TCP_ENABLED(0)到这一步新建的工程可以编译成功,接下来将测试功能是否正常,在测试之前先对modbus模块参数进行配置。在main.c文件中我们如下配置:intmain(void){eMBErrorCodeeStatus;volatileUSHORTusACLKCnt;/*StopWatchdogTimer.*/WDTCTL=WDTPW+WDTHOLD;/*DelayforACLKstartup.*/for(usACLKCnt=0xFFFF;usACLKCnt!=0;usACLKCnt--);if(cTISetDCO(TI_DCO_4MHZ)==TI_DCO_NO_ERROR){_EINT();/*InitializeProtocolStack.*/eStatus=eMBInit(MB_RTU,0x01,0,9600,MB_PAR_EVEN);if((eStatus)!=MB_ENOERR){}/*EnabletheModbusProtocolStack.*/elseif((eStatus=eMBEnable())!=MB_ENOERR){}else{for(;;){(void)eMBPoll();/*Herewesimplycountthenumberofpollcycles.*/usRegInputBuf[0]++;}}}for(;;);}这里是对modbus的串口参数以及地址的配置,这里我配置为MB_RTU,0x01,0,9600,MB_PAR_EVEN,这时modbus工作在RTU模式,节点地址为01,使用的串行端口为0也就是USART0,波特率9600,偶校验。4.还有一步很要的要修改的地方,那就是文件:port.h更改为:#defineSMCLK(8000000UL)#defineACLK(32768UL)这里定义系统时钟频率,我的开发板使用外部8MHz晶振,在dco-IAR.c中的cTISetDCO函数中我将MCU初始化为8MHz,因此SMCLK=8000000,这个参数非常重要因为串口波特率和以及定时器的计算均参考SMCLK的设置。5.到此处我们测试读写寄存器都可以通过了,但惟独测试读写线圈移植显示illegaldataaddress,,,这个地方经过返回查找实际上是由于FREEMODBUS的作者有两个回调函数并没有写实际的内容,只是单纯的返回了出错标志,我们要达到完美的移植modbus到430f149上面去,我们就必须自己重写这两个函数,此处给出了自己写的程序。eMBErrorCodeeMBRegCoilsCB(UCHAR*pucRegBuffer,USHORTusAddress,USHORTusNCoils,eMBRegisterModeeMode){eMBErrorCodeeStatus=MB_ENOERR;intiNCoils=(int)usNCoils;intusBitOffset;if(((int)usAddress=REG_COILS_START)&&(usAddress+usNCoils=REG_COILS_START+REG_COILS_SIZE)){usBitOffset=(int)(usAddress-REG_COILS_START);switch(eMode){caseMB_REG_READ:while(iNCoils0){*pucRegBuffer++=xMBUtilGetBits(ucRegCoilsBuf,usBitOffset,(unsignedint)(iNCoils8?8:iNCoils));iNCoils-=8;usBitOffset+=8;}break;caseMB_REG_WRITE:while(iNCoils0){xMBUtilSetBits(ucRegCoilsBuf,usBitOffset,(unsignedint)(iNCoils8?8:iNCoils),*pucRegBuffer++);iNCoils-=8;usBitOffset+=8;}break;}}else{eStatus=MB_ENOREG;}returneStatus;}/*eMBErrorCodeeMBRegDiscreteCB(UCHAR*pucRegBuffer,USHORTusAddress,USHORTusNDiscrete){returnMB_ENOREG;}*/eMBErrorCodeeMBRegDiscreteCB(UCHAR*pucRegBuffer,USHORTusAddress,USHORTusNDiscrete){eMBErrorCodeeStatus=MB_ENOERR;unsignedintiNDiscrete=(unsignedint)usNDiscrete;unsignedintusBitOffset;if(((int)usAddress=REG_DISCRETE_START)&&(usAddress+usNDiscrete=REG_DISCRETE_START+REG_DISCRETE_SIZE)){usBitOffset=(int)(usAddress-REG_DISCRETE_START);while(iNDiscrete0){*pucRegBuffer++=xMBUtilGetBits(ucRegDiscreteBuf,usBitOffset,(unsignedint)(iNDiscrete8?8:iNDiscrete));iNDiscrete-=8;usBitOffset+=8;}}else{eStatus=MB_ENOREG;}returneStatus;}为了配置这两个函数当然了前面还要有若干个宏定义用