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


    0 前言
        本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机。

    在该从机中定义了线圈寄存器。当中线圈寄存器地址较低的4位和EasyARM的P2.4至P2.5关联,通过modbus指令可控制GPIO的输出。本文改动自freemodbus 演示样例LINUXTCP。经过简单的改动也可用于其它Linux开发板。


        【相关博文】

        【代码仓库】
        代码仓库位于bitbucket——easyarm-modbus-tcp,请使用Hg克隆或者直接下载zip包。

    请不要使用不论什么版本号的IE浏览器訪问链接,除非你已经知道所使用的IE浏览器符合HTML5标准。推荐使用谷歌或者火狐浏览器訪问,若使用国产双核浏览器请切换到极速模式。


     1 部分代码
        【gpio-sysfs】
        在gpio-sysfs中添加使能GPIO、禁止GPIO和GPIO定期处理函数。

    当中gpio_poll传入的參数为modbus线圈寄存器

    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 $<

    2 实验
        【1】在虚拟机中make获得可运行文件——modbustcp
        【2】配置EasyARM IP地址,比如EasyARM的IP地址为192.168.1.211
        ifconfig eht0 192.168.1.211
        【2】通过tftp传输可运行文件至开发板(如果此时虚拟机的IP地址为192.168.1.106)
        tftp -g -r modbustcp 192.168.1.106
        【3】改动可运行权限。

    并运行

        chmod a+x modbustcp
        ./modbustcp
        【4】modbus tcp中有一个简单的控制台。输入h可获得指令帮助。当中e为使能协议栈。q为退出程序。

        输入e使能modbus从机协议栈。

    图1 运行modbus tcp

        【5】在windows中打开modbus调试软件,连接EasyARM。IP地址为192.168.1.211,端口号为默认端口号205。


    图2 通过modbus tcp控制GPIO

    图3 实验效果

    4 总结
    【1】操作步骤较多,实现modbus tcp须要不少的基础知识。


  • 相关阅读:
    LINQ查询操作符之First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Contains、Any、All、Coun
    .Net 使用的快捷键
    P2073 送花
    洛谷P1514 引水入城
    花园
    八数码难题
    并查集题目整理
    树链剖分(强势借鉴)
    模拟题
    考试整理
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6791188.html
Copyright © 2020-2023  润新知