tag 标签: stm8s

相关帖子
相关博文
  • 热度 25
    2013-11-26 15:07
    4459 次阅读|
    0 个评论
         FreeMODBUS一个奥地利人写的Modbus协议。它是一个针对嵌入式应用的一个免费(自由)的通用MODBUS协议的移植。Modbus是一个工业制造环境中应用的一个通用协议.。     FreeMODBUS最新版本V1.5。下载地址:http://www.freemodbus.org/index.php?idx=5    下面进行的移植基于STM8S单片机的官方固件库    1、物理层接口文件修改(具体应修改接口文件portserial.c及porttimer.c)     portserial.c文件中:     void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )函数设置串口状态。当xRxEnable为真时,应使能串口接收及接收中断。在RS485通讯系统中,还要注意将RS485接口芯片设为接收使能状态;当xTxEnable为真时,应使能串口发送及发送中断。在RS485通讯系统中,还要注意将RS485接口芯片设为发送使能状态。void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) //控制串口的收发中断 {     if(TRUE==xRxEnable)     {         UART1_ITConfig(UART1_IT_RXNE, ENABLE);     }     else     {         UART1_ITConfig(UART1_IT_RXNE, DISABLE);         }     if(TRUE==xTxEnable)     {         UART1_ITConfig(UART1_IT_TXE,ENABLE);     }     else     {        UART1_ITConfig(UART1_IT_TXE,  DISABLE);     } } BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )函数初始化串行通讯端口。参数ucPORT可以忽略;参数ulBaudRate是通讯端口的波特率,应根据此数值设置所使用硬件端口的波特率;参数ucDataBits为通讯时所使用的数据位宽,注意,若使用RTU模式,则有ucDataBits=8,若使用ASCII模式,则有ucDataBits=7,应根据此参数设置所使用硬件端口的数据位宽;eParity为校验方式,eParity=MB_PAR_NONE为无校验,此时硬件端口应设置为无校验方式及两个停止位,eParity=MB_PAR_ODD为奇校验,此时硬件端口应设置为奇校验方式及一个停止位,eParity= MB_PAR_EVEN为偶校验,此时硬件端口应设置为偶校验方式及一个停止位。函数返回值务必为TRUE。 BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) {       UART1_WordLength_TypeDef databit;       UART1_Parity_TypeDef parity;      UART1_DeInit();         if(8==ucDataBits)         {             databit = UART1_WORDLENGTH_8D;         }         else         {             databit = UART1_WORDLENGTH_9D;                 }         if(MB_PAR_NONE == eParity)         {             parity = UART1_PARITY_NO;         }         else if(MB_PAR_ODD == eParity)         {                 parity = UART1_PARITY_ODD;                 }         else         {                 parity = UART1_PARITY_EVEN;                 }         UART1_Init((uint32_t)ulBaudRate,databit, UART1_STOPBITS_1, parity,          UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);     /* ENABLE the USARTx */     UART1_ITConfig(UART1_IT_TXE, ENABLE);            return TRUE; }     BOOL xMBPortSerialPutByte( CHAR ucByte )通讯端口发送一字节数据函数。在此函数中编写发送一字节数据的函数。注意,由于使用的是中断发送,故只需将数据放到发送寄存器即可。函数返回值务必为TRUE。 BOOLxMBPortSerialPutByte( CHAR ucByte ) {     UART1_SendData8(ucByte);     return TRUE; } BOOL xMBPortSerialGetByte( CHAR * pucByte )通讯端口接收一字节数据函数。在此函数中编写接收的函数。由于使用的是中断接收,只需将接收寄存器的值放到* pucByte即可。函数返回值务必为TRUE。 BOOL xMBPortSerialGetByte( CHAR * pucByte ) {     *pucByte = UART1_ReceiveData8();     return TRUE; } void prvvUARTRxISR( void )和void prvvUARTTxReadyISR( void )无需修改。 portserial.c文件修改 BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )初始化超时定时器播函数。根据所使用的硬件初始化超时定时器,使之能产生中断时间为usTim1Timerout50us*50us的中断,本例移植采用单片机的TIM4定时器。函数返回值务必为TRUE。 BOOL xMBPortTimersInit( USHORT usTim1Timerout50us ) {   /* TIM4 configuration:    - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter    clock used is 16 MHz / 128 = 125 000 Hz   - With 125 000 Hz we can generate time base:       max time base is 2.048 ms if TIM4_PERIOD = 255 -- (255 + 1) / 125000 = 2.048 ms       min time base is 0.016 ms if TIM4_PERIOD = 1   -- (  1 + 1) / 125000 = 0.016 ms                                                            -- 16us   - In this example we need to generate a time base equal to 50us    so TIM4_PERIOD = (0.00005 * 125000 - 1) = 5 */     /* Time base configuration */   TIM4_TimeBaseInit(TIM4_PRESCALER_128, 5);   /* Clear TIM4 update flag */   TIM4_ClearFlag(TIM4_FLAG_UPDATE);   /* Enable update interrupt */   TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);     /* enable interrupts */  // enableInterrupts();   /* Enable TIM4 */   TIM4_Cmd(ENABLE);     return TRUE;; } void vMBPortTimersEnable(  )使能超时定时器函数。需在此函数中清除中断标志位、清零定时器计数值,并重新使能定时器中断。 void vMBPortTimersEnable(  ) //打开时钟 {     /* Clear TIM4 update flag */   TIM4_ClearFlag(TIM4_FLAG_UPDATE);      /* Enable update interrupt */   TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);     TIM4_SetCounter(0x00);      /* Enable TIM4 */   TIM4_Cmd(ENABLE); } void vMBPortTimersDisable(  )关闭超时定时器函数。在此函数中清零定时器计数值,并关闭定时器中断。 void vMBPortTimersDisable(  ) //关闭时钟 {     TIM4_Cmd(DISABLE);     TIM4_SetCounter(0x00);     TIM4_ITConfig(TIM4_IT_UPDATE, DISABLE);   TIM4_ClearFlag(TIM4_FLAG_UPDATE); } void prvvTIMERExpiredISR( void )函数不需修改。 2、 应用层回函数的修改     在应用层,用户需要定义所需要使用的寄存器,并修改对应的回函数。 eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )输入寄存器回函数。* pucRegBuffer为协议中所需的数据,usAddress为输入寄存器地址,usNRegs为访问寄存器的个数,eMode为访问类型(MB_REG_READ为读保持寄存器,MB_REG_WRITE为写保持寄存器)。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的寄存器地址usAddress放到相应保持寄存器中。 eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) {     eMBErrorCode  eStatus = MB_ENOERR;     int iRegIndex;     if( ( usAddress = REG_INPUT_START ) ( usAddress + usNRegs = REG_INPUT_START + REG_INPUT_NREGS ) )     {         iRegIndex = ( int )( usAddress - usRegInputStart );         while( usNRegs 0 )         {             *pucRegBuffer++ =                 ( unsigned char )( usRegInputBuf 8 );             *pucRegBuffer++ =                 ( unsigned char )( usRegInputBuf 0xFF );             iRegIndex++;             usNRegs--;         }     }     else     {         eStatus = MB_ENOREG;     }     return eStatus; } eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )保持寄存器回函数。* pucRegBuffer为要协议中的数据,usAddress为输入寄存器地址,usNRegs为访问寄存器的个数,eMode为访问类型(MB_REG_READ为读保持寄存器,MB_REG_WRITE为写保持寄存器)。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的寄存器地址usAddress放到相应保持寄存器中。 eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) {     eMBErrorCode    eStatus = MB_ENOERR;     int             iRegIndex;     u16 *PRT=(u16*)pucRegBuffer;     if( ( usAddress = REG_HOLDING_START ) ( usAddress + usNRegs = REG_HOLDING_START + REG_HOLDING_NREGS ) )     {         iRegIndex = ( int )( usAddress - usRegHoldingStart );         switch ( eMode )         {          case MB_REG_READ:             while( usNRegs 0 )             {               ////  *PRT++ = __REV16(usRegHoldingBuf ); //数据序转 REV16.W                        *pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf 8 );               *pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf 0xFF );                       iRegIndex++;               usNRegs--;             }             break;         case MB_REG_WRITE:             while( usNRegs 0 )             {               ////  usRegHoldingBuf = __REV16(*PRT++); //数据序转 REV16.W                     usRegHoldingBuf = *pucRegBuffer++ 8;               usRegHoldingBuf |= *pucRegBuffer++;               iRegIndex++;               usNRegs--;             }         }     }     else     {         eStatus = MB_ENOREG;     }     return eStatus; } eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )读/写开关寄存器 函数。* pucRegBuffer为要添加到协议中的数据,usAddress为地址,usNCoils为要访问的个数,eMode为访问类型(MB_REG_READ为读状态,MB_REG_WRITE为写)。用户应根据要访问的地址usAddress将相应的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的地址usAddress放到相应地址中。 eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode ) {     ( void )pucRegBuffer;     ( void )usAddress;     ( void )usNCoils;     ( void )eMode;     return MB_ENOREG; } eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )读开关寄存器函数。 eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) {     ( void )pucRegBuffer;     ( void )usAddress;     ( void )usNDiscrete;     return MB_ENOREG; }        
相关资源