一、首先配置W5300
1、初始化GPIO
包括FSMC(灵活的静态存储控制器)的地址总线、数据总线、读使能脚、写使能脚,片选脚。
W5300与主机的接口有直接地址模式和间接地址模式两种,总线又分为16位和8位两种。另外,W5300可以根据TEST_MODE[3:0]的不同配置选择内部PHY和外部PHY。本项目中,使用的是直接地址模式下的16位数据总线。
在16位数据总线模式下 ,只使用ADDR[9:1],而ADDR0接地或者悬空。因为“BIT16EN”有内部上拉,所以可以悬空。
硬件连接方式:
数据总线 |
数据总线 |
地址总线 |
片选 |
PD14 <-> FSMC_D0 |
PE13 <-> FSMC_D10 |
PF0 <-> FSMC_A0 |
PG10<->FSMC_NE3 |
PD15 <-> FSMC_D1 |
PE14 <-> FSMC_D11 |
PF1 <-> FSMC_A1 |
读使能 |
PD 0 <-> FSMC_D2 |
PE15 <-> FSMC_D12 |
PF2 <-> FSMC_A2 |
PD4<->FSMC_NOE |
PD1 <-> FSMC_D3 |
PD8 <-> FSMC_D13 |
PF3 <-> FSMC_A3 |
写使能 |
PE7 <-> FSMC_D4 |
PD9 <-> FSMC_D14 |
PF4 <-> FSMC_A4 |
PD5<->FSMC_NWE |
PE8 <-> FSMC_D5 |
PD10<-> FSMC_D15 |
PF5 <-> FSMC_A5 |
|
PE9 <-> FSMC_D6 |
|
PF12<->FSMC_A6 |
|
PE10 <-> FSMC_D7 |
|
PF13<->FSMC_A7 |
|
PE11 <-> FSMC_D8 |
|
PF14<->FSMC_A8 |
|
PE12 <-> FSMC_D9 |
|
PF15<->FSMC_A9 |
2、复位W5300
PLL锁相环:将25MHZ的时钟源经过6倍频,建立150MHZ的时钟用于内部单元的运行,如TCP/IP内核、主机接口管理和寄存器管理。锁相环在复位后锁定并提供稳定的时钟信号。且W5300不支持上电复位,因此必须由外部系统给出复位信号。每个SOCKET在复位后分配8K字节。
3、配置W5300的MAC地址和IP地址
MAC地址:
IP地址:
二、freemodbus tcp
主机为客户端那么modbus tcp支持多个主机,在一个局域网中可存在多个主机和多个从机。
2.1 modbus TCP和modbus RTU区别
【1】从机地址变得不再重要,多数情况下忽略。从某种意义上说从机地址被IP地址取代;
【2】CRC校验变得不再重要,甚至可以忽略。由于TCP数据包中已经存在校验,为了不重复造轮子,modbus TCP干脆取消了CRC校验。
modbus TCP和modbus RTU的区别可使用下图概括:
modbus TCP数据包和modbus RTU数据包比较
在modbus TCP中包含一个MBAP头,该头包含以下几个部分
区域 |
长度 |
描述 |
客户端 |
服务器 |
传输标志 |
2字节 |
MODBUS 请求和响应传输过程中序列号 |
客户端生成 |
应答时复制该值 |
协议标志 |
2字节 |
Modbus协议默认为0 |
客户端生成 |
应答时复制该值 |
长度 |
2字节 |
剩余部分的长度 |
客户端生成 |
应答时由服务器端生成 |
单元标志 |
1字节 |
从机标志(从机地址) |
客户端生成 |
应答时复制该值 |
注意
【1】传输标志可理解为序列号,防止MODBUS TCP通信错位,例如后发生的响应先到了主机,而早发生的响应后到主机
【2】单元标志可理解为从机地址,此时已经不再重要
2.2 modbus Tcp 和 TCP IP的关系
modbus TCP可以理解为发生在TCP上的应用层协议,既然是TCP协议那么一个完整的MODBUS TCP报文必然包括TCP首部,IP首部和Ethernet首部。
2.3 MODBUS TCP和RTU代码实现
首先下载最新的modbus源码,在https://www.embedded-experts.at/en/freemodbus-downloads/下载最新的版本freemodbus-v1.5,下载最新的协议不仅可以防止被人改动导致自己做无用功,保持原生态也可以很好的与制定者进行交流。解压freemodbus-v1.5,目录结构很清晰,主要有四个文件件,分别是demo、modbus、tools、doc。其中tools为上位机测试modbus程序,doc为一些说明文件先不讨论。有用的是demo以及modbus。打开demo,没有看到stm32的工程文件,有一个叫BARE的文件夹,是一些不包括任何处理器的部分源代码,我们就用这个建立工程文件。
W5300工程中加入BARE的文件夹下的port以及modbus文件夹,将BARE的文件夹demo中的函数拷贝到W5300工程中。
2.3.1 定义本地端口
2.3.2 循环检测W5300状态寄存器Sn_SSR
①调用getSn_SR(SOCK_UDPS)函数检测Sn_SSR寄存器的状态,如果检测socket关闭,则出现连接UDP;②如果socket处于UDP模式,调用getSn_RX_RSR(SOCK_UDPS),获取Sn_RX_RSR(接收数据的字节长度寄存器,它指示SOCKET内部RX存储器接收数据的字节长度)的状态。③如果接收的字节长度大于0,调用recvfrom接收函数。④调用xMBPortEventPost( EV_FRAME_RECEIVED )函数,发送已接收到数据到modbus tcp状态机。
eMBErrorCode eMBTCPInit( USHORT ucTCPPort )
eMBEnable()函数流程
eMBEventType枚举类型变量定义了event事件的类型。
Modbus的主查询函数eMBPoll()的流程
(1)当事件为EV_FRAME_RECEIVED(接收到完整数据帧)时,调用peMBFrameReceiveCur函数,即modbus RTU或者TCP接收处理函数。
xMBTCPPortGetRequest()函数中** ppucMBTCPFrame为一个指向数据的指针,而*ppucMBTCPFrame可以指向一个数组,在这里可把ucTCPRequestFrame复制给该变量,配合usTCPLength,那么从uIP接收到的内容就”转移“到freemodbus中。
(2)当事件为EV_EXECUTE(接收功能函数)时,按照eMBPoll()的EV_EXECUTE事件流程。peMBFrameSendCur()函数→eMBTCPSend()函数→xMBTCPPortSendResponse()函数。