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"
#include "dco.h"
/* ----------------------- Start implementation -----------------------------*/
char cTISetDCO( int delta )
{
char z,result;
/*------选择主系统时钟为8MHZ -------*/
BCSCTL1 &= ~XT2OFF; //打开XT2高频振荡器
do
{
IFG1 &= ~OFIFG; //清除振荡器失效标志
for (z = 0xFF; z > 0; 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.
更改为:
/* ----------------------- Platform includes --------------------------------*/
#include <msp430x14x.h>
#if defined (__GNUC__)
#include <signal.h>
#endif
#undef CHAR
Portserial.c 中usOldSR = _DINT( )程序,_DINT()是没有返回值的所以编译会报错,
将该部分程序更改为这样
文件:Portserial.c---EnterCriticalSection( void )
更改为:
void
EnterCriticalSection( void )
{
USHORT usOldSR;
if( ucCriticalNesting == 0 )
{
#if defined (__GNUC__)
usOldSR = READ_SR;
_DINT( );
#else
// usOldSR = _DINT( );
#endif
// ucGIEWasEnabled = usOldSR & GIE ? TRUE : FALSE;
_DINT( );
ucGIEWasEnabled = TRUE;
}
ucCriticalNesting++;
}
文件:Portserial.c--- ExitCriticalSection( void )
更改为:
void
ExitCriticalSection( void )
{
ucCriticalNesting--;
if( ucCriticalNesting == 0 )
{
if( ucGIEWasEnabled )
{
ucGIEWasEnabled = FALSE;
_EINT( );
}
}
}
更改中断服务函数,原程序的中断服务函数格式不能在IAR 中使用,因此要更改为IAR
格式
文件:portserial.c---prvvMBSerialRXIRQHandler( void )
USB重定向更改为:
#pragma vector = USART0RX_VECTOR
__interrupt
void
prvvMBSerialRXIRQHandler( void ) //__interrupt[USART0RX_VECTOR]
{
DEBUG_TOGGLE_RX( );
pxMBFrameCBByteReceived( );
}
文件:portserial.c--- prvvMBSerialTXIRQHandler ( void )
更改为:
#pragma vector = USART0TX_VECTOR
__interrupt
void
prvvMBSerialTXIRQHandler( void ) // __interrupt[USART0TX_VECTOR]
{
DEBUG_TOGGLE_TX( );
pxMBFrameCBTransmitterEmpty( );
}
文件:porttimer.c--- prvvMBTimerIRQHandler ( void )
更改为:
#pragma vector = TIMERA0_VECTOR
__interrupt
void
prvvMBTimerIRQHandler( 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 ------------------------------------------*/
#define REG_INPUT_START 0
#define REG_INPUT_NREGS 4
#define REG_HOLDING_START 0
#define REG_HOLDING_NREGS 125
这里配置modbus 支持的工作模式,有RTU、ASCII、TCP 三种模式。0 表示失能,1 表
示使能。这里我只开启RTU 模式,当然了你也可以选择都开启。
文件:mbconfig.h
更改为:
/*! \brief If Modbus ASCII support is enabled. */
#define MB_ASCII_ENABLED ( 0 )
/*! \brief If Modbus RTU support is enabled. */
#define MB_RTU_ENABLED ( 1 )
/*! \brief If Modbus TCP support is enabled. */
#define MB_TCP_ENABLED ( 0 )
到这一步新建的工程可以编译成功,接下来将测试功能是否正常,在测试之前先对
modbus 模块参数进行配置。
在main.c文件中我们如下配置:
int main( void )
{
eMBErrorCode eStatus;
volatile USHORT usACLKCnt;
/* Stop Watchdog Timer. */
WDTCTL = WDTPW + WDTHOLD;
/* Delay for ACLK startup. */
for( usACLKCnt = 0xFFFF; usACLKCnt != 0; usACLKCnt-- );
if( cTISetDCO( TI_DCO_4MHZ ) == TI_DCO_NO_ERROR )
{
_EINT( );
/* Initialize Protocol Stack. */
eStatus = eMBInit( MB_RTU, 0x01, 0, 9600, MB_PAR_EVEN );
if( (eStatus ) != MB_ENOERR )
{
}
/* Enable the Modbus Protocol Stack. */
else if( ( eStatus = eMBEnable( ) ) != MB_ENOERR )
{
}
else
选址方法 {
for( ;; )
{
( void )eMBPoll( );
/* Here we simply count the number of poll cycles. */
usRegInputBuf[0]++;
}
}
}
for( ;; );
}
这里是对modbus 的串口参数以及地址的配置,这里我配置为MB_RTU, 0x01, 0, 9600,
MB_PAR_EVEN,这时modbus 工作在RTU 模式,节点地址为01,使用的串行端口为0 也就
是USART0,波特率9600,偶校验。
4.还有一步很要的要修改的地方,那就是
文件:port.h
更改为:
三基光源
#define SMCLK ( 8000000UL )
#define ACLK ( 32768UL )
这里定义系统时钟频率,我的开发板使用外部8MHz 晶振,在dco-IAR.c 中的cTISetDCO
函数中我将MCU 布鲁加达综合征初始化为8MHz,因此SMCLK = 8000000 ,这个参数非常重要因为串口波
规划沙盘