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 $<
图2 通过modbus tcp控制GPIO
图3 实验效果
4 总结 【1】操作步骤较多,实现modbus tcp需要不少的基础知识。
EasyARM i.mx28学习笔记——通过modbus tcp控制GPIO,布布扣,bubuko.com