大家好!
我正在尝试在我的 TM4C123GH6PM 中实现 Freemodbus 堆栈 、 我已经进行了一些测试、但没有成功。
希望能得到一些帮助或建议非常感谢、以下是我已经完成的步骤
1.首先,我下载了 freemodbus-v 1.4.0文件夹,并在相应的端口文件夹中进行“更改”,
port.h
/* FreeModbus Libary:Bare Port * Copyright (C) 2006 Christian Walter * *此库是免费软件;您可以根据 免费软件基金会发布的 GNU Lesser General Public *许可证的条款重新分发和/或*修改它; *许可证2.1版或(您可以选择)任何更高版本。 * *发布本库的目的是希望其有用 、*但不作任何保证;甚至没有* 适销性或特定用途适用性的暗示保证。 有关 详细信息、请参阅 GNU * Lesser General Public License。 * *您应该已经收到 GNU Lesser General Public *许可证以及此库的副本;如果没有,请写信至 Free Software * Foundation、Inc.,51 Franklin St,Fifth Floor,Boston, ma 02110-1301 USA * *文件:$ID:port.h、v 1.1 2006/08/221:35:13 wolti Exp$ */ #ifndef _port_H #define _port_H /*------ 平台包括: */ #include "incTM4c123.h" #include #define内联 内联 #define PR_BEGIN_EXTERN extern "C"{ #definePR_END_extern _C} #define enter_critical SECTION () ROM_IntMasterDisable () #define EXIT_CRITICAL_SECTION () ROM_IntMasterEnable () typedef uint8_t BOOL; typedef unsigned char UCHAR; typedef char char; typedef uint16_t USHORT; tyf Int16_t short; tyINT32_t Ulong typedef int32_t long; #ifndef true #define true 1 #endif #ifndef false #define false 0 #endif #endif
因此、.h 文件 IncTm4c123.h 只是一个头文件、我在其中放置相应的头文件以使用外设函数、我忘记了提到我正在使用 TivaWare 2.1.4.178、IDE 是 IAR 8.0
根据 我的理解、使用或需要使用常量:ENTER_CRITICAL_SECTION 和 EXIT_CRITIC_SECTION 来禁用器件对象上的中断、以便禁用所有处理器中断
在 portation.dox 文件之后、下一个要更改的文件是
porttimer.c
/*---------------- 平台包括: */ #include "port.h" #include "IncTM4C123.h" /*---------------- Modbus 包括------------------ */ #include "mb.h" #include "mbport.h" /*-------------- 静态函数------------------------------------------------------- ///static void prvTIMER ExpiredISR( void ); /*-------------- 我的函数------------------------------------------- */ USHORT usMBMulDiv (USHORT A、USHORT b、USHORT c); /*-------------- 持久性变量------------------------------------------------------- */ USHORT usDelta; /*-------------- 开始执行--- // USHORT usMBMulDiv (USHORT A、USHORT b、USHORT c){ Ulong x; x = a; x *= b; x /= c; return (USHORT) x; } //时间参数 usTim1Timerout50us 是50us 的倍数 //因此,为了计算计时器节拍,请使用函数 usMBMMulDiv BOOL xMBPortTimersInit( USHORT usTim1Timerout50us ) { ROM_SysCtlPeripheralEnable (sysctl_Periph_TIMER0); ROM_TIMERConfigure (TIMER0_BASE、TIMER_CFG_ONE_SHOT);//全宽32位和针对 freemodmus 要求计时器需要是一次性 //定义要加载到寄存器 中的数字 usDelta = usMBMulDiv (usTim1Timerout50us、800、100); ROM_IntMasterIMA ();//启用 TIMER0A/ENABLE_TIMER TOOT/ END/ TOOTTIMER 0/ TOVERT 超时(/inc/hw_ints.h);启用 TIMER0_INT_INTERRUPT 返回 true; } void vMBPortTimersEnable()//仅启动计时 器{ /*在超时传递给 xMBPortTimersInit()时启用定时器*/ ROM_TimerLoadSet (TIMER0_BASE、TIMER_A、usDelta); ROM_TimerEnable (TIMER0_BASE、TIMER_A);//启用定时器 ROM_TimerIntEnable (TIMER0_BASE、 Timer_TINA_TIMEOUT); ROM_TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT); } void vMBPortTimersDisable() { /*禁用任何挂起的计时器。 / ROM_TIMERDisable (TIMER0_BASE、TIMER_A); ROM_TIMERIntDisable (TIMER0_BASE、TIMER_TINA_TIMEOUT); ROM_TIMERIntClear (TIMER0_BASE、TIMER_TIMA_TIMEOUT); } /*创建一个 ISR,该 ISR 在计时器过期时调用。 然后,此函数*必须调用 pxMBPortCBTimerExpired (),以通知协议栈 *计时器已过期。 */ void Timer0IntHandler( void ){ ROM_TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT); ROM_TimerIntDisable (TIMER0_BASE、TIMER_TINA_TIMEOUT); ( void )pxMBPortCBTimerExpired (); }
我已经使用以下所述的代码来测试此部件:
xMBPortTimersInit(20); vMBPortTimersEnable();
似乎可以正常工作、只需打开 Timer0 ISR (Timer0IntHandler (void))中的 LED
下一个...
portserial.c
#include "port.h" /*---------------------- Modbus 包括------------------ */ #include "mb.h" #include "mbport.h" /*-------------- 静态函数------------------------------------------------------- /*static void prvUARTTxReadyISR( void ); static void prvUARTRxISR( void ); */ /*--- 开始执行--- // void vMBPortSerialEnable( BOOL xRxEnable,BOOL xTxEnable ) {// If xRXEnable 启用串行接收中断。 如果启用了 xTxENable *发送器为空中断。 // if (xRxEnable) { UARTIntEnable (UART0_BASE、UART_INT_RX); }否则 UARTIntDisable (UART0_BASE、UART_INT_RX); if (xTxEnable) { UARTIntEnable (UART0_BASE、UART_INT_TX); }否则 UARTIntDisable (UART0_BASE、UART_INT_TX); } BOOL xMBPortSerialInit( UCHAR ucPORT、Ulong ulBaudRate、UCHAR ucDataBits、eMBParity eParity) { (空) ucPORT; uint32_t 奇偶校验、位、秒位; // //启用 UART 使用的 GPIO 外设。 // ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //启用 UART0 // ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0); // //为 UART 模式配置 GPIO 引脚。 // ROM_GPIOPinConfigure (GPIO_PA0_U0RX); ROM_GPIOPinConfigure (GPIO_PA1_U0TX); ROM_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); // //选择 UART 的长度和奇偶校验 // switch (eParity) { case MB_PAR_EVEN: 奇偶校验= UART_CONFIG_PAR_EVEN; stopbits = UART_CONFIG_STOP_ONE; break; case MB_PAR_ODD: 奇偶校验= UART_CONFIG_PAR_ODD; stopbits = UART_CONFIG_ST_NOT_11 ;stop_bits = UART_UART_CONFIG = UART_11字符格式/确保 UART_CONFIG break; } switch( ucDataBits ) { 案例8: bits = UART_CONFIG_WLEN_8; break; 案例7: bits = UART_CONFIG_WLEN_7; break; } // //初始化控制台 I/O 的 UART // ROM_UARTConfigSetExpClk (UART0_BASE、ROM_SysCtlClockGet ()、ulBaudRate、 (BITS | stopbits | 奇偶校验); //禁用 FIFO,以确保中断仅用于 RX 的更改 UARTFIFODisable (UART0_BASE); // //启用 UART 和中断 // ROM_IntEnable (INT_UART0); // vMBPortSerialEnable (true、true); 返回 true; } BOOL xMBPortSerialPutByte (char ucByte) { /*在 UART 发送缓冲区中放入一个字节。 此函数被调用 *如果 pxMBFrameCBTransmitterEmpty()已经存在,则按协议栈 *被调用。 */ UARTCharPut( UART0_BASE,ucByte ); 返回 true; } BOOL xMBPortSerialGetByte (char * pucByte)//提供@以放置新的 char { /*返回 UART 接收缓冲区中的字节。 此函数被调用 *在调用 pxMBFrameCBByteRecepto()后由协议栈提供。 * // //无 FIFO。 // 操作 { * pucByte = ROM_UARTCharGet (UART0_BASE); } while (ROM_UARTCharsAvail (UART0_BASE)); 返回 true; } void UARTIntHandler (void) { uint32_t ui32status; ui32status = ROM_UARTIntStatus (UART0_BASE,TRUE); //为目标 *处理器的接收中断创建中断处理程序。 然后,此函数应调用 pxMBFrameCBByteRecepthat()。 然后,*协议栈将调用 xMBPortSerialGetByte()以检索 *字符。 // if (ui32status == UART_INT_RX) { pxMBFrameCBByteReceived(); ROM_UARTIntClear ( UART0_BASE,ui32status ); } /*为 目标处理器创建发送缓冲区空中断*(或等效中断)的中断处理程序。 然后,此函数 应*调用 pxMBFrameCBTransmitterEmpty(),它告知协议栈 *可以发送新字符。 然后,协议栈将调用 * xMBPortSerialPutByte()发送字符。 // if (ui32status =UART_INT_TX) { pxMBFrameCBTransmitterEmpty (); ROM_UARTIntClear (UART0_BASE、ui32status); }
在这里、我不确定是否可以禁用 UART 的 FIFO、但我只想确保只有在引脚发生变化时才会发生中断
我只尝试使用这部分从 PC 发送字符的代码、并打开 UART ISR 中的 LED、它工作正常。
最后、主要内容:
main.c
#include "incTM4c123.h" #include #include "mb.h" #include "mbport.h" /*------------------ 定义了------------------------------------------------------- // #define REG_INPUT_START 1000 #define REG_INPUT_NREGS 4 static unsigned usRegInputStart = REG_INPUT_START; static unsigned usRegInputBuf[REG_INPUT_NREGS]; void configure (void); eMBErrorCode eMBRegInputCB (UCHAR * pucRegBuffer、USHORT) eMBErrorCode EStatus = MB_ENOERR; 内部 iRegIndex; if ((usAddress >= REG_INPUT_START) &&(usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS) { iRegIndex =( int )( usAddress - usRegInputStart ); while (usNRegs >0) { *puRegBuffer++= (unsigned char)(usRegInputBuf[iRegIndex]>> 8); *puRegBuffer++= (unsigned char)(usRegInputBuf[iRegIndex]& 0xFF); iRegIndex++; usNRegs--; } } 其他 { EStatus = MB_ENOREG; } 返回 EStatus; } eMBErrorCode eMBRegHoldingCB (UCHAR * puRegBuffer、USHORT usAddress、USHORT usNRegs、 eMBRegisterMode eMode) { 返回 MB_ENOREG; } eMBErrorCode eMBRegCoilsCB (UCHAR * puRegBuffer、USHORT usAddress、USHORT usNils、 eMBRegisterMode eMode) { 返回 MB_ENOREG; } eMBErrorCode eMBRegDisconteCB( UCHAR * puRegBuffer、USHORT usAddress、USHORT us离散) { 返回 MB_ENOREG; } //----------------- main int main() { configureMBIN(MB_RTU ,0x01,0,9600, mb_par_none); //启用 Modbus 协议栈。 */ eMBEnable(); for (;;) { ( void )eMBPoll(); /*在这里、我们只计算轮询周期数。 * usRegInputBuf[0]++; } } void 配置(void){ ROM_SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);// 16MHz clk ROM_SysTL_SysT1_GPIO PeripheralEnable (SYSCTL_Periph_GPIOF);ROM_GPIOPINTypeGP2_BASE (GPIO_IN_GPIOPTF);GPIO_PIN_IN_IN_INP0_GPIO_IN_IN_GPIO_IN_IN_GPIOPTF);GPIO_IN_IN_IN_IN_GPIO_IN_IN_IN_IN_IN_IN_IN_IN_INP0_GPIO_IN_IN_IN_
我只想使用 RTU 模式、因此在 mbconfig.h 中、我在 ASCII 和 TCP 宏中放置了0、我在 Linux 中使用了 Modpoll Modbus Master Simulator、参数为:
:$./modpoll -m RTU -a 1 -r 1000 -c 4 -t 3 -b 9600 -d 8 -p 无/dev/ttyACM0
对从属方没有答案:/我真的很难,我会尝试在 FIFO 上做一些更改,也许这会有帮助,但我只是想知道有人是否处理过这个问题, 并告诉我是否正在正确修改文件
谢谢、致以最诚挚的问候!