大家好!
我正在尝试在我的 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 上做一些更改,也许这会有帮助,但我只是想知道有人是否处理过这个问题, 并告诉我是否正在正确修改文件
谢谢、致以最诚挚的问候!