您的位置:首页 > 博客中心 > 数据库 >

EasyARM i.mx28学习笔记——通过modbus tcp控制GPIO

时间:2022-03-13 22:41

0 前言     本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机。在该从机中定义了线圈寄存器,其中线圈寄存器地址较低的4位和EasyARM的P2.4至P2.5关联,通过modbus指令可控制GPIO的输出。本文修改自freemodbus 示例LINUXTCP,经过简单的修改也可用于其他Linux开发板。
int gpio_enable(void) { gpio_export(P24);gpio_direction(P24,OUT);gpio_write(P24,0); gpio_export(P25);gpio_direction(P25,OUT);gpio_write(P25,0); gpio_export(P26);gpio_direction(P26,OUT);gpio_write(P26,0); gpio_export(P27);gpio_direction(P27,OUT);gpio_write(P27,0); return 0; } int gpio_disable(void) { gpio_write(P24,0);gpio_unexport(P24); gpio_write(P25,0);gpio_unexport(P25); gpio_write(P26,0);gpio_unexport(P26); gpio_write(P27,0);gpio_unexport(P27); return 0; } int gpio_poll(unsigned char status) { status & 0x01 ? gpio_write(P24,1) : gpio_write(P24,0); status & 0x02 ? gpio_write(P25,1) : gpio_write(P25,0); status & 0x04 ? gpio_write(P26,1) : gpio_write(P26,0); status & 0x08 ? gpio_write(P27,1) : gpio_write(P27,0); return 0; }     【modbus poll】     pvPollingThread线程中获得线圈寄存器结果——ucRegCoilsBuf[0],并传递至gpio_poll函数中。

void* pvPollingThread( void *pvParameter )
{
    eSetPollingThreadState( RUNNING );
    if( eMBEnable( ) == MB_ENOERR )
    {
        do
        {
            gpio_poll(ucRegCoilsBuf[0]); // 改变IO口状态
            if( eMBPoll( ) != MB_ENOERR )
                break;
        }
        while( eGetPollingThreadState( ) != SHUTDOWN );
    }
    ( void )eMBDisable( );
    eSetPollingThreadState( STOPPED );
    return 0;
}
    【线圈寄存器读写函数】
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
    eMBErrorCode eStatus = MB_ENOERR;
    int iNCoils = ( int )usNCoils;
    int usBitOffset;
   
    if( ( usAddress >= REG_COILS_START ) &&
       ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
    {

        usBitOffset = ( int )( usAddress - REG_COILS_START );
        switch ( eMode )
        {
        case MB_REG_READ:
            while( iNCoils > 0 )
            {
                *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
                                                 ( UCHAR )( iNCoils > 8 ? 8 : iNCoils ) );
                iNCoils -= 8;
                usBitOffset += 8;
            }
            break;
           
        case MB_REG_WRITE:
            while( iNCoils > 0 )
            {
                xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
                               ( UCHAR )( iNCoils > 8 ? 8 : iNCoils ),
                               *pucRegBuffer++ );
                iNCoils -= 8;
                usBitOffset += 8;
            }
            break;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}
    【makefile】
# 指定编译器
CROSS = arm-fsl-linux-gnueabi-
CC = $(CROSS)gcc
STRIP = $(CROSS)strip

# CFLAG包括头文件目录
CFLAGS = -g -Wall

# 头文件查找路径
INC = -I. -Iport -I../../modbus/rtu         -I../../modbus/ascii -I../../modbus/include -I../../modbus/tcp

#
LIBS = -lpthread
# 目标
TARGET = modbustcp
# 源文件
SRC = demo.c gpio-sysfs.c port/portother.c     port/portevent.c port/porttcp.c     ../../modbus/mb.c ../../modbus/tcp/mbtcp.c     ../../modbus/functions/mbfunccoils.c     ../../modbus/functions/mbfuncdiag.c     ../../modbus/functions/mbfuncholding.c     ../../modbus/functions/mbfuncinput.c     ../../modbus/functions/mbfuncother.c     ../../modbus/functions/mbfuncdisc.c     ../../modbus/functions/mbutils.c

# 源文件编译为目标文件
OBJS = $(SRC:.c=.o)

.PHONY: clean

# 链接为可执行文件
$(TARGET): $(OBJS)
    $(CC) $^ -o $@ $(LIBS)
    $(STRIP) $@

# 可执行文件和目标文件
clean:
    rm -f $(OBJS)
    rm -f $(TARGET)

# 连续动作,先清除再编译链接,复制到tftpboot中
install:clean $(TARGET)
    @echo 复制到tftpboot目录
    cp $(TARGET) ~/tftpboot
    @echo 复制结束

# 编译规则 加入头文件 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.c
    $(CC) $(CFLAGS) $(INC) -o $@ -c $<


gxlsystem.com,布布扣
图2 通过modbus tcp控制GPIO gxlsystem.com,布布扣
图3 实验效果
4 总结 【1】操作步骤较多,实现modbus tcp需要不少的基础知识。

EasyARM i.mx28学习笔记——通过modbus tcp控制GPIO,布布扣,bubuko.com

热门排行

今日推荐

热门手游