Modbus TCP多主站数据监测要实现的功能为:两个及以上的TCP客户端同时访问STM32服务器的传感器数据。
文章目录
- 一、实验原理
- 二、CubeMx工程创建
- 三、关键代码实现
- 四、完整工程代码链接
一、原理介绍
1. Modbus简介
Modbus是一种串行通讯协议,已广泛应用与当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其他设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。其通讯遵循以下的过程:
- 主设备向从设备发送请求;
- 从设备分析并处理主设备的请求,然后向主设备发送结果;
- 如果出现任何差错,从设备将返回一个异常功能码。
Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本。其中Modbus RTU与Modbus ASCII均为支持RS-485总线的通信协议,其中Modbus RTU由于其采用二进制表现形式以及紧凑数据结构。而Modbus ASCII由于采用ASCII码传输,并利用特殊字符作为其字节的开始与结束标识。而Modbus TCP协议则是在RTU协议上加一个MBAP报文头,由于TCP是基于可靠连接的服务,不再需要CRC校验,简单的说就是:Modbus TCP协议就是Modbus RTU协议在前面加上五个0以及一个6,然后去掉两个CRC校验码字节。
Modbus TCP协议的相关介绍可参考博客:
带你玩转modbusTCP通信_modbustcp协议数据格式-优快云博客
2. SPI简介
SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供空间,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。SPI的通信原理很简单,它以主动方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据传输)、SDO(数据输出)、SCLK(时钟)、CS(片选)。
- MISO:主设备数据输入,从设备数据输出。
- MOSI:主设备数据输出,从设备数据输入。
- SCLK:时钟信号,由主设备产生。
- CS:从设备片选信号,由主设备控制。
SPI通信的相关介绍可参考博客:
3. STM32F407IGT6 W5500以太网驱动简介
iCore3开发板带有W5500嵌入式以太网控制器,支持实现MODBUS TCP功能。W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。W5500集成了TCP/IP协议栈,10/100M以太网数据链路层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。久经市场考验的WIZnet全硬件TCP/IP协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP 以及PPPoE协议。W5500内嵌32K字节片上缓存以供以太网包处理。如果你使用W5500,你只需要一些简单的Socket编程就能实现以太网应用。这将会比其他嵌入式以太网方案更加快捷、简便。用户可以同时使用8个硬件Socket独立通讯。W5500提供了SPI(外设串行接口)从而能够更加容易与外设MCU整合。而且,W5500使用了新的高效SPI协议支持80MHz速率,从而能够更好的实现高速网络通讯。Mobus是开放协议,IANA给协议赋予TCP端口502,iCore3的IP地址为192.168.0.1,PC1的IP地址为192.168.0.2,PC2的IP地址为192.168.0.3,在建立完客户端与服务器之间的TCP连接后,Modbus即可通信。W5500工作原理图如下图所示:
W5500 有 1 个通用寄存器, 8 个 Socket 寄存器区,以及对应每个 Socket 的收发缓存区。每个区域均通过 SPI 数据帧的区域选择位(BSB[4:0])来选取。
(1)通用寄存器区配置了 W5500 的基本信息。
1)GAR (网关 IP 地址寄存器) [R/W] [0x0001 – 0x0004] [0x00]
该寄存器用来设置默认网关地址,例如: “192.168.0.1
2)SUBR (子网掩码寄存器) [R/W] [0x0005 – 0x0008] [0x00]
该寄存器用来设置子网掩码地址,例如“255.255.255.0”。
3)SHAR (源 MAC 地址寄存器) [R/W] [0x0009 – 0x000E] [0x00]
该寄存器用来设置源 MAC 地址。例如: “00.08.DC.01.02.03”。
4)SIPR (客户端地址寄存器) [R/W] [0x000F – 0x0012] [0x00]
该寄存器用来设置服务器 IP 地址。例如: “192.168.0.2”。
(2)Socket 端口寄存器
1)Sn_DIPR (Socket 目标 IP 地址寄存器) [R/W] [0x000C-0x000F] [0x00000000]
Sn_DIPR配置或指示的为 Socket n 的客户端 IP 地址,在 TCP/UDP 模式下生效。在 TCP 客户端模式下,在 CONNECT 配置命令前,该寄存器设置新增粉丝了 TCP 服务器的 IP 地址。例如: Socket 0 的目标 IP 地址= 192.168.0.11, 配置应如下:
2)Sn_DPORT (Socket n 目标端口寄存器) [R/W] [0x0010-0x0011] [0x00]
Sn_DPORT 配置或指示了 Socket n 的目标主机端口号,在 TCP/UDP 模式下生效。在 TCP 客户端模式下,在 CONNET 配置命令前,该寄存器配置了 TCP Server监听的端口号。例如: Socket 0 的目标端口号 = 5000,配置应如下:
二、CubeMx工程创建
1. 在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR。
2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置。在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本文选取的芯片型号为:STM32F407IGTx。
3. 配置RCC,使用外部时钟源,可以不用直接去配置引脚状态,PH0和PH1引脚会自动配置时钟。
4. 配置调试引脚,同样可以不用直接去设置引脚,PA13和PA14引脚会自动配置为调试引脚。
5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output,参数设置参考下图,请配置完进行核对。
6. 配置SPI引脚模式,PA7--SPI1_MOSI,PB3--SPI1_SCK,PB4--SPI1_MISO,PA15--GPIO_Output(单独设置)。
7.时钟源设置,选择外部高速时钟源,配置为最大主频。
8. 工程文件的设置, 这里就是工程的各种配置。因为涉及到文件读写,堆栈调大一些。
三、关键代码实现
//主函数,多主站监听关键实现
int main(void)
{
/* USER CODE BEGIN 1 */
int receive_length;
int i;
short int data;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_ADC3_Init();
MX_SPI1_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
LED_GREEN_ON;
adc1.initialize();
spi1.initialize();
w5500.initialize();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE BEGIN 3 */
for(i = 0;i < 5;i++){
adc1.read(i); //读ADC的值
}
/*将数据存放在寄存器中*/
data = adc1.value[0] * 1000 * 6;
hold_reg[0] = data >> 8;
hold_reg[1] = data & 0xff;
data = adc1.value[1] * 1000 / 2;
hold_reg[2] = data >> 8;
hold_reg[3] = data & 0xff;
data = adc1.value[2] * 1000;
hold_reg[4] = data >> 8;
hold_reg[5] = data & 0xff;
data = adc1.value[3] * 1000 * 2;
hold_reg[6] = data >> 8;
hold_reg[7] = data & 0xff;
data = adc1.value[4] * 1000 * 2;
hold_reg[8] = data >> 8;
hold_reg[9] = data & 0xff;
//2024/1/9 Add
LED_GREEN_OFF;
LED_RED_ON;
switch(getSn_SR(0)) //获取socket0的状态
{
case SOCK_INIT: //socket初始化完成
listen(0); //监等待连接
break;
case SOCK_ESTABLISHED: //socket连接建立
if(getSn_IR(0) & Sn_IR_CON)
{
setSn_IR(0, Sn_IR_CON); //Sn_IR的第0位置1
}
receive_length=getSn_RX_RSR(0); //获取已接收数据大小
if(receive_length>0)
{
recv(0,buffer,12); //接收数据
modbus_tcp.process(); //modbus数据处理
LED_RED_OFF;
}
break;
case SOCK_CLOSE_WAIT: //socket等待关闭状态
disconnect(0);
break;
case SOCK_CLOSED: //socket关闭
socket(0,Sn_MR_TCP,30000,Sn_MR_ND);//打开socket0的一个端口
break;
}
switch(getSn_SR(1)) //获取socket1的状态
{
case SOCK_INIT: //socket初始化完成
listen(1); //监听等待连接
break;
case SOCK_ESTABLISHED: //socket连接建立
if(getSn_IR(1) & Sn_IR_CON)
{
setSn_IR(1, Sn_IR_CON); //Sn_IR的第1位置1
}
receive_length=getSn_RX_RSR(1); //获取已接收数据大小
if(receive_length>0)
{
recv(1,buffer,12); //接收数据
modbus_tcp.process(); //modbus数据处理
LED_RED_OFF;
}
break;
case SOCK_CLOSE_WAIT: //socket等待关闭状态
disconnect(1);
break;
case SOCK_CLOSED: //socket关闭
socket(1,Sn_MR_TCP,60000,Sn_MR_ND);//打开socket1的一个端口
break;
}
}
/* USER CODE END 3 */
}
//socket 实现
/*
*
@file socket.c
@brief setting chip register for socket
last update : 2013. Nov
*
*/
#include "stdio.h"
#include "w5500.h"
#include "socket.h"
static uint16 local_port;
extern uint16 sent_ptr;
/**
@brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5200 done it.
@return 1 for sucess else 0.
*/
uint8 socket(SOCKET s, uint8 protocol, uint16 port, uint8 flag)
{
uint8 ret;
if (
((protocol&0x0F) == Sn_MR_TCP) ||
((protocol&0x0F) == Sn_MR_UDP) ||
((protocol&0x0F) == Sn_MR_IPRAW) ||
((protocol&0x0F) == Sn_MR_MACRAW) ||
((protocol&0x0F) == Sn_MR_PPPOE)
)
{
close(s);
IINCHIP_WRITE(Sn_MR(s) ,protocol | flag);
if (port != 0) {
IINCHIP_WRITE( Sn_PORT0(s) ,(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_PORT1(s) ,(uint8)(port & 0x00ff));
} else {
local_port++; // if don't set the source port, set local_port number.
IINCHIP_WRITE(Sn_PORT0(s) ,(uint8)((local_port & 0xff00) >> 8));
IINCHIP_WRITE(Sn_PORT1(s) ,(uint8)(local_port & 0x00ff));
}
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_OPEN); // run sockinit Sn_CR
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s)));
/* ------- */
ret = 1;
// if( (IINCHIP_READ(Sn_SR(s)) & 0xff ) != SOCK_INIT){
// IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
// }
// IINCHIP_WRITE(Sn_CR(s) , Sn_CR_LISTEN);
//
// while(IINCHIP_READ(Sn_CR(s)) != 0);
//
// if( (IINCHIP_READ(Sn_SR(s)) &0XFF )!= SOCK_LISTEN){
// IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
// }
}
else
{
ret = 0;
}
return ret;
}
/**
@brief This function close the socket and parameter is "s" which represent the socket number
*/
void close(SOCKET s)
{
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_CLOSE);
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s)) );
/* ------- */
/* all clear */
IINCHIP_WRITE( Sn_IR(s) , 0xFF);
}
/**
@brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer.
@return 1 for success else 0.
*/
uint8 listen(SOCKET s)
{
uint8 ret;
if (IINCHIP_READ( Sn_SR(s) ) == SOCK_INIT)
{
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_LISTEN);
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s) ) )
;
/* ------- */
ret = 1;
}
else
{
ret = 0;
}
return ret;
}
/**
@brief This function established the connection for the channel in Active (client) mode.
This function waits for the untill the connection is established.
@return 1 for success else 0.
*/
uint8 connect(SOCKET s, uint8 * addr, uint16 port)
{
uint8 ret;
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
{
ret = 0;
}
else
{
ret = 1;
// set destination IP
IINCHIP_WRITE( Sn_DIPR0(s), addr[0]);
IINCHIP_WRITE( Sn_DIPR1(s), addr[1]);
IINCHIP_WRITE( Sn_DIPR2(s), addr[2]);
IINCHIP_WRITE( Sn_DIPR3(s), addr[3]);
IINCHIP_WRITE( Sn_DPORT0(s), (uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_DPORT1(s), (uint8)(port & 0x00ff));
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_CONNECT);
/* wait for completion */
while ( IINCHIP_READ(Sn_CR(s) ) ) ;
while ( IINCHIP_READ(Sn_SR(s)) != SOCK_SYNSENT )
{
if(IINCHIP_READ(Sn_SR(s)) == SOCK_ESTABLISHED)
{
break;
}
if (getSn_IR(s) & Sn_IR_TIMEOUT)
{
IINCHIP_WRITE(Sn_IR(s), (Sn_IR_TIMEOUT)); // clear TIMEOUT Interrupt
ret = 0;
break;
}
}
}
return ret;
}
/**
@brief This function used for disconnect the socket and parameter is "s" which represent the socket number
@return 1 for success else 0.
*/
void disconnect(SOCKET s)
{
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_DISCON);
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s) ) )
;
/* ------- */
}
/**
@brief This function used to send the data in TCP mode
@return 1 for success else 0.
*/
uint16 send(SOCKET s, const uint8 * buf, uint16 len)
{
uint8 status=0;
uint16 ret=0;
uint16 freesize=0;
if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
else ret = len;
// if freebuf is available, start.
do
{
freesize = getSn_TX_FSR(s);
status = IINCHIP_READ(Sn_SR(s));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
{
ret = 0;
break;
}
} while (freesize < ret);
// copy data
send_data_processing(s, (uint8 *)buf, ret);
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_SEND);
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s) ) );
while ( (IINCHIP_READ(Sn_IR(s) ) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
{
status = IINCHIP_READ(Sn_SR(s));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT) )
{
// uart4.printf("SEND_OK Problem!!\r\n");
close(s);
return 0;
}
}
IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);
#ifdef __DEF_IINCHIP_INT__
putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);
#endif
return ret;
}
/**
@brief This function is an application I/F function which is used to receive the data in TCP mode.
It continues to wait for data as much as the application wants to receive.
@return received data size for success else -1.
*/
uint16 recv(SOCKET s, uint8 * buf, uint16 len)
{
uint16 ret=0;
if ( len > 0 )
{
recv_data_processing(s, buf, len);
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_RECV);
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s) ));
/* ------- */
ret = len;
}
return ret;
}
/**
@brief This function is an application I/F function which is used to send the data for other then TCP mode.
Unlike TCP transmission, The peer's destination address and the port is needed.
@return This function return send data size for success else -1.
*/
uint16 sendto(SOCKET s, const uint8 * buf, uint16 len, uint8 * addr, uint16 port)
{
uint16 ret=0;
if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
else ret = len;
if( ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00)) )//||(ret == 0) )
{
/* added return value */
ret = 0;
}
else
{
IINCHIP_WRITE( Sn_DIPR0(s), addr[0]);
IINCHIP_WRITE( Sn_DIPR1(s), addr[1]);
IINCHIP_WRITE( Sn_DIPR2(s), addr[2]);
IINCHIP_WRITE( Sn_DIPR3(s), addr[3]);
IINCHIP_WRITE( Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_DPORT1(s),(uint8)(port & 0x00ff));
// copy data
send_data_processing(s, (uint8 *)buf, ret);
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_SEND);
/* wait to process the command... */
while( IINCHIP_READ( Sn_CR(s) ) )
;
/* ------- */
while( (IINCHIP_READ( Sn_IR(s) ) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
{
if (IINCHIP_READ( Sn_IR(s) ) & Sn_IR_TIMEOUT)
{
/* clear interrupt */
IINCHIP_WRITE( Sn_IR(s) , (Sn_IR_SEND_OK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
return 0;
}
}
IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);
}
return ret;
}
/**
@brief This function is an application I/F function which is used to receive the data in other then
TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
@return This function return received data size for success else -1.
*/
uint16 recvfrom(SOCKET s, uint8 * buf, uint16 len, uint8 * addr, uint16 *port)
{
uint8 head[8];
uint16 data_len=0;
uint16 ptr=0;
uint32 addrbsb =0;
if ( len > 0 )
{
ptr = IINCHIP_READ(Sn_RX_RD0(s) );
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD1(s));
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x18;
switch (IINCHIP_READ(Sn_MR(s) ) & 0x07)
{
case Sn_MR_UDP :
wiz_read_buf(addrbsb, head, 0x08);
ptr += 8;
// read peer's IP address, port number.
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
data_len = head[6];
data_len = (data_len << 8) + head[7];
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x18;
wiz_read_buf(addrbsb, buf, data_len);
ptr += data_len;
IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
break;
case Sn_MR_IPRAW :
wiz_read_buf(addrbsb, head, 0x06);
ptr += 6;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
data_len = head[4];
data_len = (data_len << 8) + head[5];
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x18;
wiz_read_buf(addrbsb, buf, data_len);
ptr += data_len;
IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
break;
case Sn_MR_MACRAW :
wiz_read_buf(addrbsb, head, 0x02);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
if(data_len > 1514)
{
// uart4.printf("data_len over 1514\r\n");
while(1);
}
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x18;
wiz_read_buf(addrbsb, buf, data_len);
ptr += data_len;
IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
break;
default :
break;
}
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_RECV);
/* wait to process the command... */
while( IINCHIP_READ( Sn_CR(s)) ) ;
/* ------- */
}
return data_len;
}
#ifdef __MACRAW__
void macraw_open(void)
{
uint8 sock_num;
uint16 dummyPort = 0;
uint8 mFlag = 0;
sock_num = 0;
close(sock_num); // Close the 0-th socket
socket(sock_num, Sn_MR_MACRAW, dummyPort,mFlag); // OPen the 0-th socket with MACRAW mode
}
uint16 macraw_send( const uint8 * buf, uint16 len )
{
uint16 ret=0;
uint8 sock_num;
sock_num =0;
if (len > getIINCHIP_TxMAX(sock_num)) ret = getIINCHIP_TxMAX(sock_num); // check size not to exceed MAX size.
else ret = len;
send_data_processing(sock_num, (uint8 *)buf, len);
//W5500 SEND COMMAND
IINCHIP_WRITE(Sn_CR(sock_num),Sn_CR_SEND);
while( IINCHIP_READ(Sn_CR(sock_num)) );
while ( (IINCHIP_READ(Sn_IR(sock_num)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK );
IINCHIP_WRITE(Sn_IR(sock_num), Sn_IR_SEND_OK);
return ret;
}
uint16 macraw_recv( uint8 * buf, uint16 len )
{
uint8 sock_num;
uint16 data_len=0;
uint16 dummyPort = 0;
uint16 ptr = 0;
uint8 mFlag = 0;
sock_num = 0;
if ( len > 0 )
{
data_len = 0;
ptr = IINCHIP_READ(Sn_RX_RD0(sock_num));
ptr = (uint16)((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(sock_num) );
//-- read_data(s, (uint8 *)ptr, data, len); // read data
data_len = IINCHIP_READ_RXBUF(0, ptr);
ptr++;
data_len = ((data_len<<8) + IINCHIP_READ_RXBUF(0, ptr)) - 2;
ptr++;
if(data_len > 1514)
{
uart4.printf("data_len over 1514\r\n");
uart4.printf("\r\nptr: %X, data_len: %X", ptr, data_len);
//while(1);
/** recommand : close and open **/
close(sock_num); // Close the 0-th socket
socket(sock_num, Sn_MR_MACRAW, dummyPort,mFlag); // OPen the 0-th socket with MACRAW mode
return 0;
}
IINCHIP_READ_RXBUF_BURST(sock_num, ptr, data_len, (uint8*)(buf));
ptr += data_len;
IINCHIP_WRITE(Sn_RX_RD0(sock_num),(uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE(Sn_RX_RD1(sock_num),(uint8)(ptr & 0x00ff));
IINCHIP_WRITE(Sn_CR(sock_num), Sn_CR_RECV);
while( IINCHIP_READ(Sn_CR(sock_num)) ) ;
}
return data_len;
}
#endif
//w5500驱动 参考银杏科技
/*
* FILE : w5500.c
* DESCRIPTION : This file is iCore3 files.
* Author : ysloveivy
* Copyright :
*
* History
* --------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* --------------------
*/
//--------------------------- Include ---------------------------//
#include "spi1.h"
#include "gpio.h"
#include "spi.h"
#include "w5500.h"
#include "main.h"
#include "socket.h"
//--------------------- Function Prototype ----------------------//
static void delay(int ms);
static int initialize(void);
static int setup(SOCKET s, unsigned char protocol, unsigned short int port, unsigned char flag);
//--------------------------- Variable --------------------------//
W5500_T w5500={
.initialize=initialize,
.setup=setup
};
static unsigned short int local_port;
unsigned char txsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};
unsigned char rxsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};
static unsigned char I_STATUS[MAX_SOCK_NUM];
static unsigned short int SSIZE[MAX_SOCK_NUM]; /**< Max Tx buffer size by each channel */
static unsigned short int RSIZE[MAX_SOCK_NUM]; /**< Max Rx buffer size by each channel */
//--------------------------- Function --------------------------//
/*
* Name : getISR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char getISR(unsigned char s)
{
return I_STATUS[s];
}
/*
* Name : putISR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void putISR(unsigned char s, unsigned char val)
{
I_STATUS[s] = val;
}
/*
* Name : getIINCHIP_RxMAX
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int getIINCHIP_RxMAX(unsigned char s)
{
return RSIZE[s];
}
/*
* Name : getIINCHIP_TxMAX
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int getIINCHIP_TxMAX(unsigned char s)
{
return SSIZE[s];
}
/*
* Name : IINCHIP_CSoff
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void IINCHIP_CSoff(void)
{
SPI1_CS_OFF;
}
/*
* Name : IINCHIP_CSon
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void IINCHIP_CSon(void)
{
SPI1_CS_ON;
}
/*
* Name : IINCHIP_SpiSendData
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char IINCHIP_SpiSendData(unsigned char dat)
{
return(spi1.send_data(dat));
}
/*
* Name : IINCHIP_WRITE
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void IINCHIP_WRITE( unsigned long int addrbsb, unsigned char data)
{
SPI1_CS_OFF;
spi1.send_data( (addrbsb & 0x00FF0000)>>16); // Address byte 1
spi1.send_data( (addrbsb & 0x0000FF00)>> 8); // Address byte 2
spi1.send_data( (addrbsb & 0x000000F8) + 4); // Data write command and Write data length 1
spi1.send_data(data); // Data write (write 1byte data)
SPI1_CS_ON;
}
/*
* Name : IINCHIP_READ
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char IINCHIP_READ(unsigned long int addrbsb)
{
unsigned char data = 0;
SPI1_CS_OFF;
spi1.send_data( (addrbsb & 0x00FF0000)>>16); // Address byte 1
spi1.send_data( (addrbsb & 0x0000FF00)>> 8); // Address byte 2
spi1.send_data( (addrbsb & 0x000000F8)) ; // Data read command and Read data length 1
data = spi1.send_data(0x00); // Data read (read 1byte data)
SPI1_CS_ON;
return data;
}
/*
* Name : wiz_write_buf
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int wiz_write_buf(unsigned long int addrbsb,unsigned char* buf,unsigned short int len)
{
unsigned short int idx = 0;
SPI1_CS_OFF;
spi1.send_data( (addrbsb & 0x00FF0000)>>16); // Address byte 1
spi1.send_data( (addrbsb & 0x0000FF00)>> 8); // Address byte 2
spi1.send_data( (addrbsb & 0x000000F8) + 4); // Data write command and Write data length 1
for(idx = 0; idx < len; idx++) // Write data in loop
{
spi1.send_data(buf[idx]);
}
SPI1_CS_ON;
return len;
}
/*
* Name : wiz_read_buf
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int wiz_read_buf(unsigned long int addrbsb, unsigned char* buf,unsigned short int len)
{
unsigned short int idx = 0;
SPI1_CS_OFF;
spi1.send_data( (addrbsb & 0x00FF0000)>>16); // Address byte 1
spi1.send_data( (addrbsb & 0x0000FF00)>> 8); // Address byte 2
spi1.send_data( (addrbsb & 0x000000F8)); // Data write command and Write data length 1
for(idx = 0; idx < len; idx++) // Write data in loop
{
buf[idx] = spi1.send_data(0x00);
}
SPI1_CS_ON;
return len;
}
/*
* Name : iinchip_init
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void iinchip_init(void)
{
setMR( MR_RST );
}
/*
* Name : sysinit
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void sysinit( unsigned char * tx_size, unsigned char * rx_size )
{
short int i;
short int ssum,rsum;
ssum = 0;
rsum = 0;
for (i = 0 ; i < MAX_SOCK_NUM; i++) // Set the size, masking and base address of Tx & Rx memory by each channel
{
IINCHIP_WRITE( (Sn_TXMEM_SIZE(i)), tx_size[i]);
IINCHIP_WRITE( (Sn_RXMEM_SIZE(i)), rx_size[i]);
SSIZE[i] = (int16)(0);
RSIZE[i] = (int16)(0);
if (ssum <= 16384)
{
switch( tx_size[i] )
{
case 1:
SSIZE[i] = (int16)(1024);
break;
case 2:
SSIZE[i] = (int16)(2048);
break;
case 4:
SSIZE[i] = (int16)(4096);
break;
case 8:
SSIZE[i] = (int16)(8192);
break;
case 16:
SSIZE[i] = (int16)(16384);
break;
default :
RSIZE[i] = (int16)(2048);
break;
}
}
if (rsum <= 16384)
{
switch( rx_size[i] )
{
case 1:
RSIZE[i] = (int16)(1024);
break;
case 2:
RSIZE[i] = (int16)(2048);
break;
case 4:
RSIZE[i] = (int16)(4096);
break;
case 8:
RSIZE[i] = (int16)(8192);
break;
case 16:
RSIZE[i] = (int16)(16384);
break;
default :
RSIZE[i] = (int16)(2048);
break;
}
}
ssum += SSIZE[i];
rsum += RSIZE[i];
}
}
/*
* Name : setGAR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setGAR(unsigned char * addr)
{
wiz_write_buf(GAR0, addr, 4);
}
/*
* Name : getGWIP
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void getGWIP(unsigned char * addr)
{
wiz_read_buf(GAR0, addr, 4);
}
/*
* Name : setSUBR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSUBR(unsigned char * addr)
{
wiz_write_buf(SUBR0, addr, 4);
}
/*
* Name : setSHAR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSHAR(unsigned char * addr)
{
wiz_write_buf(SHAR0, addr, 6);
}
/*
* Name : setSIPR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSIPR(unsigned char * addr)
{
wiz_write_buf(SIPR0, addr, 4);
}
/*
* Name : getGAR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void getGAR(unsigned char * addr)
{
wiz_read_buf(GAR0, addr, 4);
}
/*
* Name : getSUBR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void getSUBR(unsigned char * addr)
{
wiz_read_buf(SUBR0, addr, 4);
}
/*
* Name : getSHAR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void getSHAR(unsigned char * addr)
{
wiz_read_buf(SHAR0, addr, 6);
}
/*
* Name : getSIPR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void getSIPR(unsigned char * addr)
{
wiz_read_buf(SIPR0, addr, 4);
}
/*
* Name : setMR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setMR(unsigned char val)
{
IINCHIP_WRITE(MR,val);
}
/*
* Name : getIR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char getIR( void )
{
return IINCHIP_READ(IR);
}
/*
* Name : setRTR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setRTR(unsigned short int timeout)
{
IINCHIP_WRITE(RTR0,(unsigned char)((timeout & 0xff00) >> 8));
IINCHIP_WRITE(RTR1,(unsigned char)(timeout & 0x00ff));
}
/*
* Name : setRCR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setRCR(unsigned char retry)
{
IINCHIP_WRITE(WIZ_RCR,retry);
}
/*
* Name : clearIR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void clearIR(unsigned char mask)
{
IINCHIP_WRITE(IR, ~mask | getIR() ); // must be setted 0x10.
}
/*
* Name : setSn_MSS
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSn_MSS(SOCKET s, unsigned short int Sn_MSSR)
{
IINCHIP_WRITE( Sn_MSSR0(s), (unsigned char)((Sn_MSSR & 0xff00) >> 8));
IINCHIP_WRITE( Sn_MSSR1(s), (unsigned char)(Sn_MSSR & 0x00ff));
}
/*
* Name : setSn_TTL
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSn_TTL(SOCKET s, unsigned char ttl)
{
IINCHIP_WRITE( Sn_TTL(s) , ttl);
}
/*
* Name : getSn_IR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char getSn_IR(SOCKET s)
{
return IINCHIP_READ(Sn_IR(s));
}
/*
* Name : getSn_SR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned char getSn_SR(SOCKET s)
{
return IINCHIP_READ(Sn_SR(s));
}
/*
* Name : getSn_TX_FSR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int getSn_TX_FSR(SOCKET s)
{
unsigned short int val=0,val1=0;
do
{
val1 = IINCHIP_READ(Sn_TX_FSR0(s));
val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
if (val1 != 0)
{
val = IINCHIP_READ(Sn_TX_FSR0(s));
val = (val << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
}
} while (val != val1);
return val;
}
/*
* Name : getSn_RX_RSR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
unsigned short int getSn_RX_RSR(SOCKET s)
{
unsigned short int val=0,val1=0;
do
{
val1 = IINCHIP_READ(Sn_RX_RSR0(s));
val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
if(val1 != 0)
{
val = IINCHIP_READ(Sn_RX_RSR0(s));
val = (val << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
}
} while (val != val1);
return val;
}
/*
* Name : send_data_processing
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void send_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
unsigned short int ptr = 0;
unsigned long int addrbsb = 0;
ptr = IINCHIP_READ( Sn_TX_WR0(s) );
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s));
addrbsb = ((uint32)ptr<<8) + (s<<5) + 0x10;
wiz_write_buf(addrbsb, data, len);
ptr += len;
IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_TX_WR1(s),(uint8)(ptr & 0x00ff));
}
/*
* Name : recv_data_processing
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void recv_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
unsigned short int ptr = 0;
unsigned long int addrbsb = 0;
ptr = IINCHIP_READ( Sn_RX_RD0(s) );
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(s) );
addrbsb = ((uint32)ptr<<8) + (s<<5) + 0x18;
wiz_read_buf(addrbsb, data, len);
ptr += len;
IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
}
/*
* Name : setSn_IR
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
void setSn_IR(unsigned char s, unsigned char val)
{
IINCHIP_WRITE(Sn_IR(s), val);
}
/*
* Name : initialize
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int initialize(void) //初始化设置
{
unsigned char mac[6]={0x00,0x98,0xdc,0x42,0x61,0x11};
unsigned char lip[4]={192,168,0,10};
unsigned char sub[4]={255,255,255,0};
unsigned char gw[4]={192,168,0,1};
delay(2000);
while((IINCHIP_READ(PHYCFGR)& LINK)==0); //等待以太网连接完成
setMR( MR_RST );
delay(100);
setSHAR(mac);
setSUBR(sub);
setGAR(gw);
setSIPR(lip);
sysinit(txsize,rxsize);
setRTR(2000); /*设置溢出时间值*/
setRCR(8); /*设置最大重新发送次数*/
IINCHIP_WRITE( IMR,IM_IR7 | IM_IR6);
IINCHIP_WRITE( SIMR, S0_IMR);
IINCHIP_WRITE( Sn_IMR(0), IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);
return 0;
}
/*
* Name : setup
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int setup(SOCKET s, uint8 protocol, uint16 port, uint8 flag)
{
if(s > 7)return -1;
w5500.flag[s].send_ok=1;
uint8 ret;
if (
((protocol&0x0F) == Sn_MR_TCP) ||
((protocol&0x0F) == Sn_MR_UDP) ||
((protocol&0x0F) == Sn_MR_IPRAW) ||
((protocol&0x0F) == Sn_MR_MACRAW) ||
((protocol&0x0F) == Sn_MR_PPPOE)
)
{
close(s);
IINCHIP_WRITE(Sn_MR(s) ,protocol | flag);
if (port != 0) {
IINCHIP_WRITE( Sn_PORT0(s) ,(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_PORT1(s) ,(uint8)(port & 0x00ff));
} else {
local_port++; // if don't set the source port, set local_port number.
IINCHIP_WRITE(Sn_PORT0(s) ,(uint8)((local_port & 0xff00) >> 8));
IINCHIP_WRITE(Sn_PORT1(s) ,(uint8)(local_port & 0x00ff));
}
IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_OPEN); // run sockinit Sn_CR
/* wait to process the command... */
while( IINCHIP_READ(Sn_CR(s))!= 0);
/* ------- */
ret = 1;
if( (IINCHIP_READ(Sn_SR(s)) & 0xff ) != SOCK_INIT){
IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
}
IINCHIP_WRITE(Sn_CR(s) , Sn_CR_LISTEN);
while(IINCHIP_READ(Sn_CR(s)) != 0);
if( (IINCHIP_READ(Sn_SR(s)) &0XFF )!= SOCK_LISTEN){
IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
}
}
else
{
ret = 0;
}
return ret;
}
/*
* Name : delay
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 0.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static void delay(int ct) //ms
{
int i, j;
for (i = 0; i < ct; i++)
{
for (j = 0; j < 10000; j++) ;
}
}
//Modbus TCP代码
/*
* FILE : modbus_tcp.c
* DESCRIPTION :--
* Author : ysloveivy.
* Copyright :
*
* History
* --------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* --------------------
*/
//-----------------Include files-------------------------//
#include "modbus_tcp.h"
#include "main.h"
#include "socket.h"
#include "w5500.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
//---------------------- Define ---------------------//
//---------------- Function prototype ---------------//
static char process(void);
static int mb_rsq_pdu(unsigned char *receive_buffer_temp,int cnt);
static int mb_excep_rsq_pdu(unsigned char *receive_buffer_temp,int error_code);
static int function_1(unsigned char *receive_buffer_temp);
static int function_2(unsigned char *receive_buffer_temp);
static int function_3(unsigned char *receive_buffer_temp);
static int function_4(unsigned char *receive_buffer_temp);
static int function_5(unsigned char *receive_buffer_temp,int cnt);
static int function_6(unsigned char *receive_buffer_temp,int cnt);
static int broadcast(unsigned char *receive_buffer_temp);
//---------------- varitable -----------------------//
MODBUS_TCP_T modbus_tcp = {
.process = process,
};
char discrete_input[32] = {0x55,0x55,0x55};
char coil[32] = {0x55,0x55,0x55};
char input_reg[20] = {0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10};
char hold_reg[512] = {0};
unsigned char receive_buffer_temp[100];
//---------------- Function ------------------------//
/*
* Name : process
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static char process(void)
{
memcpy(receive_buffer_temp,buffer,12);
memset(buffer,0,12);
mb_rsq_pdu(receive_buffer_temp,12);
return 0;
}
/*
* Name : mb_rsq_pdu
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int mb_rsq_pdu(unsigned char *receive_buffer_temp,int counter_temp)
{
if(receive_buffer_temp[0 + 6] == 0x01){
switch(receive_buffer_temp[1 + 6]){
case 1:
function_1(receive_buffer_temp);
break;
case 2:
function_2(receive_buffer_temp);
break;
case 3:
function_3(receive_buffer_temp);
break;
case 4:
function_4(receive_buffer_temp);
break;
case 5:
function_5(receive_buffer_temp,counter_temp);
break;
case 6:
function_6(receive_buffer_temp,counter_temp);
break;
default :
mb_excep_rsq_pdu(receive_buffer_temp,1);
break;
}
}else if(receive_buffer_temp[0 + 6] == 0){
broadcast(receive_buffer_temp);
}
return 0;
}
/*
* Name : function_1
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_1(unsigned char *receive_buffer_temp)
{
int i;
unsigned short cnt;
unsigned short coil_num;
unsigned short start_address;
int temp = 0;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
coil_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6];
if((start_address + coil_num) > 255){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
receive_buffer_temp[2 + 6] = ((coil_num % 8 )? (coil_num / 8 + 1) : (coil_num / 8));
cnt = receive_buffer_temp[2 + 6] + 5 - 2;
if(coil_num % 8){
if(coil_num < 8){
for(i = 0;i < coil_num;i ++)temp |= 1 << i;
receive_buffer_temp[3 + 6] = ((coil[start_address / 8]) >> (start_address % 8) | (coil[start_address / 8 + 1]) << (8 - (start_address % 8))) & temp;
}else {
for(i = 0;i < receive_buffer_temp[2 + 6] - 1;i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8] << ((8 - (coil_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (coil_num % 8));
}
}else {
for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
}
receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
receive_buffer_temp[5] = (cnt & 0x00ff);
cnt = cnt + 6;
send(0,receive_buffer_temp,cnt);
return 0;
}
/*
* Name : function_2
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_2(unsigned char *receive_buffer_temp)
{
int i;
unsigned short cnt;
unsigned short discrete_num;
unsigned short start_address;
int temp = 0;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
discrete_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6];
if((start_address + discrete_num) > 255){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
receive_buffer_temp[2 + 6] = ((discrete_num % 8 )? (discrete_num / 8 + 1) : (discrete_num / 8));
cnt = receive_buffer_temp[2 + 6] + 5 - 2;
if(discrete_num % 8){
if(discrete_num < 8){
for(i = 0;i < discrete_num;i ++)temp |= 1 << i;
receive_buffer_temp[3 + 6] = ((discrete_input[start_address / 8]) >> (start_address % 8) | (discrete_input[start_address / 8 + 1]) << (8 - (start_address % 8))) & temp;
}else {
for(i = 0;i < receive_buffer_temp[2 + 6] - 1;i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8));
receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8] << ((8 - (discrete_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (discrete_num % 8));
}
}else {
for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8));
}
receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
receive_buffer_temp[5] = (cnt & 0x00ff);
cnt = cnt + 6;
send(0,receive_buffer_temp,cnt);
return 0;
}
/*
* Name : function_3
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_3(unsigned char *receive_buffer_temp)
{
int i;
int cnt;
unsigned short int start_address;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2;
if(receive_buffer_temp[2 + 6] > 48){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
if((start_address * 2 + receive_buffer_temp[2]) > 512){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
cnt = receive_buffer_temp[2 + 6] + 5 - 2;
for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[i + 3 + 6] = hold_reg[start_address * 2 + i];
receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
receive_buffer_temp[5] = (cnt & 0x00ff);
cnt = cnt + 6;
send(0,receive_buffer_temp,cnt);
send(1,receive_buffer_temp,cnt);
return 0;
}
/*
* Name : function_4
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_4(unsigned char *receive_buffer_temp)
{
int i;
int cnt;
unsigned short int start_address;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2;
if((start_address * 2 + receive_buffer_temp[2 + 6]) > 20){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
cnt = receive_buffer_temp[2] + 5 - 2;
for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[i + 3 + 6] = input_reg[start_address * 2 + i];
receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
receive_buffer_temp[5] = (cnt & 0x00ff);
cnt = cnt + 6;
send(0,receive_buffer_temp,cnt);
return 0;
}
/*
* Name : function_5
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_5(unsigned char *receive_buffer_temp,int counter_temp)
{
unsigned short start_address;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
if(start_address > 255){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){
coil[(start_address / 8)] |= 1 << start_address % 8;
}else if((receive_buffer_temp[4 + 6] == 0x00) && (receive_buffer_temp[5 + 6] == 0x00)){
coil[(start_address / 8)] &= ~(1 << start_address % 8);
}else {
mb_excep_rsq_pdu(receive_buffer_temp,3);
}
receive_buffer_temp[4] = (6 & 0xff00) >> 8;
receive_buffer_temp[5] = (6 & 0x00ff);
send(0,receive_buffer_temp,counter_temp);
return 0;
}
/*
* Name : function_6
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int function_6(unsigned char *receive_buffer_temp,int counter_temp)
{
unsigned short start_address;
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
if(start_address > 255){
mb_excep_rsq_pdu(receive_buffer_temp,2);
return 1;
}
hold_reg[start_address * 2] = receive_buffer_temp[4 + 6];
hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6];
receive_buffer_temp[4] = (6 & 0xff00) >> 8;
receive_buffer_temp[5] = (6 & 0x00ff);
send(0,receive_buffer_temp,counter_temp);
return 0;
}
/*
* Name : mb_excep_rsq_pdu
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int mb_excep_rsq_pdu(unsigned char *receive_buffer_temp,int error_code)
{
receive_buffer_temp[1 + 6] |= 0x80;
switch(error_code) {
case 1:
receive_buffer_temp[2 + 6] = 1;
break;
case 2:
receive_buffer_temp[2 + 6] = 2;
break;
case 3:
receive_buffer_temp[2 + 6] = 3;
break;
case 4:
receive_buffer_temp[2 + 6] = 4;
break;
default :
break;
}
receive_buffer_temp[4] = (3 & 0xff00) >> 8;
receive_buffer_temp[5] = (3 & 0x00ff);
send(0,receive_buffer_temp,9);
return 0;
}
/*
* Name : broadcast
* Description : ---
* Author : ysloveivy.
*
* History
* ----------------------
* Rev : 1.00
* Date : 12/20/2015
*
* create.
* ----------------------
*/
static int broadcast(unsigned char *receive_buffer_temp)
{
int start_address;
switch(receive_buffer_temp[1 + 6]){
case 5:
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
if(start_address > 255){
return 1;
}
if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){
coil[(start_address / 8)] |= 1 << start_address % 8;
}else if((receive_buffer_temp[4 + 6] == 0x00) && (receive_buffer_temp[5 + 6] == 0x00)){
coil[(start_address / 8)] &= ~(1 << start_address % 8);
}
break;
case 6:
start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
if(start_address > 255){
return 1;
}
hold_reg[start_address * 2] = receive_buffer_temp[4 + 6];
hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6];
break;
}
return 0;
}