|**银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801** ||| |技术支持邮件|Gingko@vip.163.com ||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-08-01 | gingko | 初次建立 | \\ \\ \\ \\ \\ ===== STM32CubeMX教程二十三——LAN_TCPC实验 ===== 1. 新建工程:在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR {{ :icore3:icore3_cube_23_1.png?direct | }} 2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32F407IGTx。 {{ :icore3:icore3_cube_23_2.png?direct | }} 3. 配置RCC,使用外部时钟源 {{ :icore3:icore3_cube_23_3.png?direct | }} 4. 配置调试引脚 {{ :icore3:icore3_cube_23_4.png?direct | }} 5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output {{ :icore3:icore3_cube_23_5.png?direct | }} 6. 引脚模式配置 {{ :icore3:icore3_cube_23_6.png?direct | }} 7. 配置SPI {{ :icore3:icore3_cube_23_7.png?direct | }} 选用PA15引脚作为SPI1_CS {{ :icore3:icore3_cube_23_8.png?direct | }} 8. 时钟源设置,选择外部高速时钟源,配置为最大主频 {{ :icore3:icore3_cube_23_9.png?direct | }} 9. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK5 {{ :icore3:icore3_cube_23_10.png?direct | }} 10. 点击Code Generator,进行进一步配置 {{ :icore3:icore3_cube_23_11.png?direct | }} * **Copy all used libraries into the project folder** * 将HAL库的所有.C和.H都复制到所建工程中 * 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便 * 缺点:体积大,编译时间很长 * **Copy only the necessary library files** * 只复制所需要的.C和.H(推荐) * 优点:体积相对小,编译时间短,并且工程可复制拷贝 * 缺点:新增外设时需要重新用STM32CubeMX导入 * **Add necessary library files as reference in the toolchain project configuration file** * 不复制文件,直接从软件包存放位置导入.C和.H * 优点:体积小,比较节约硬盘空间 * 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径 自行选择方式即可 11. 然后点击GENERATE CODE 创建工程 {{ :icore3:icore3_cube_23_12.png?direct | }} 创建成功,打开工程。 \\ \\ \\ \\ ===== 实验二十三:LAN_TCPC实验——以太网数据传输 ===== ==== 一、 实验目的与意义 ==== - 了解STM32的SPI和W5500的TCPC结构 - 了解STM32的SPI和W5500的TCPC特征 - 掌握SPI和TCPC的使用方法 - 掌握STM32 HAL库中SPI和TCPC的配置方法 - 掌握KEIL MDK集成开发环境使用方法 ==== 二、 实验设备及平台 ==== - iCore3 双核心板。[[https://item.taobao.com/item.htm?spm=a1z10.1-c.w4024-251734887.3.5923532fXD2RIN&id=524229438677&scene=taobao_shop|点击购买]] - JLINK(或相同功能)仿真器。[[https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-251734908.13.20822b61MmPeNN&id=554869837940|点击购买]] - Micro USB线缆。 - 网线 - Keil MDK 开发平台。 - STM32CubeMX开发平台。 - 装有WIN XP(及更高版本)系统的计算机。 ==== 三、 实验原理 ==== === 1、SPI简介 === * SPI是串行外围设备接口,全称Serial Peripheral interface,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。 * SPI 主要特点有: - 可以同时发出和接收串行数据; - 可以当作主机或从机工作; - 提供频率可编程时钟; - 发送结束中断标志; - 写冲突保护; - 总线竞争保护等; * SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。 - MISO 主设备数据输入,从设备数据输出。 - MOSI 主设备数据输出,从设备数据输入。 - SCLK时钟信号,由主设备产生。 - CS从设备片选信号,由主设备控制。当有多个从设备的时候,因为每个从设备上都有一个片选引脚接入到主设备机中,当我们的主设备和某个从设备通信时将需要将从设备对应的片选引脚电平拉低或者是拉高。 {{ :icore3:icore3_arm_hal_23_1.png?direct |}} * 在一个SPI时钟周期内,会完成如下操作: - 主设备通过MOSI线发送1位数据,从设备通过该线读取这1位数据; - 从设备通过MISO线发送1位数据,主设备通过该线读取这1位数据。 * 这是通过移位寄存器来实现的。主机和从机都有一个串行移位寄存器,随着时钟脉冲,数据按照从高位到低位的方式依次移出主设备寄存器和从机寄存器,并且依次移入从设备寄存器和主设备寄存器。当寄存器中的内容全部移出时,相当于完成了两个寄存器内容的交换。 * 主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。寄存器通过MOSI信号线将字节传送给主机,从机也将自己的移位寄存器中的内容通过MISO信号线返回给主机,这样两个移位寄存器中的内容就被交换,外设的写操作和读操作是同时进行的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。 {{ :icore3:icore3_arm_hal_23_2.png?direct |}} * iCore3 双核心板采用的ARM控制器为STM32F407IGT6,SPI接口引脚选用的是PB3(SPI1_SCK)、PB4(SPI1_MISO)、PA7(SPI1_MOSI)和PA15(CS)这4个引脚。初始化SPI,通过SPI读写控制W5500内部寄存器。 {{ :icore3:icore3_arm_hal_23_3.png?direct |}} {{ :icore3:icore3_arm_hal_23_4.png?direct |}} {{ :icore3:icore3_arm_hal_23_5.png?direct |}} === 2、W5500简介 === * 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速率,从而能够更好的实现高速网络通讯。 * W5500 有 1 个通用寄存器, 8 个 Socket 寄存器区,以及对应每个 Socket 的收发缓存区。每个区域均通过 SPI 数据帧的区域选择位(BSB[4:0])来选取。 * (1)通用寄存器区配置了 W5500 的基本信息。 * GAR (网关 IP 地址寄存器) [R/W] [0x0001 – 0x0004] [0x00] * 该寄存器用来设置默认网关地址,例如: “192.168.0.1”。 {{ :icore3:icore3_arm_hal_23_6.png?direct |}} * SUBR (子网掩码寄存器) [R/W] [0x0005 – 0x0008] [0x00] * 该寄存器用来设置子网掩码地址,例如“255.255.255.0”。 {{ :icore3:icore3_arm_hal_23_7.png?direct |}} * SHAR (源 MAC 地址寄存器) [R/W] [0x0009 – 0x000E] [0x00] * 该寄存器用来设置源 MAC 地址。例如: “00.08.DC.01.02.03”。 {{ :icore3:icore3_arm_hal_23_8.png?direct |}} * SIPR (源 IP 地址寄存器) [R/W] [0x000F – 0x0012] [0x00] * 该寄存器用来设置源 IP 地址。例如: “192.168.0.2”。 {{ :icore3:icore3_arm_hal_23_9.png?direct |}} * (2)Socket 端口寄存器 * Socket寄存器用于建立socket通信。TCP是一种连接的通信。两个socket连接之前,必定要有一个Socket处在监听状态,而另一个socket启动连接,处于监听状态的就是服务器,启动连接的Socket就是客户端。启动TCP连接之前,必须正确设置Socket的目标IP和目的端口号。以下为配置目标IP地址和目的端口号的Socket寄存器。 * 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, 配置应如下: {{ :icore3:icore3_arm_hal_23_10.png?direct |}} * Sn_DPORT (Socket n 目标端口寄存器) [R/W] [0x0010-0x0011] [0x00] * Sn_DPORT 配置或指示了 Socket n 的目标主机端口号,在 TCP/UDP 模式下生效。在 TCP 客户端模式下,在 CONNET 配置命令前,该寄存器配置了 TCP Server监听的端口号。例如: Socket 0 的目标端口号 = 5000(0x1388) ,配置应如下: {{ :icore3:icore3_arm_hal_23_11.png?direct |}} === 3、TCPC简介 === * TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内[1] 另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。 * 基于TCP/IP协议的服务器和客户端程序的一般流程,如下图所示: {{ :icore3:icore3_arm_hal_23_12.png?direct |}} * 客户端与服务器在使用TCP传输协议时要先建立一个“通道”,在传输完毕之后又要关闭这“通道”,前者可以被形象地成为“三次握手”,而后者则可以被称为“四次挥手”。 * 通道的建立——三次握手: - 在建立通道时,客户端首先要向服务端发送一个SYN同步信号。 - 服务端在接收到这个信号之后会向客户端发出SYN同步信号和ACK确认信号。 - 当服务端的ACK和SYN到达客户端后,客户端与服务端之间的这个“通道”就会被建立起来 * 通道的关闭——四次挥手: - 在数据传输完毕之后,客户端会向服务端发出一个FIN终止信号 - 服务端在收到这个信号之后会向客户端发出一个ACK确认信号 - 如果服务端此后也没有数据发给客户端时服务端会向客户端发送一个FIN终止信号 - 客户端在收到这个信号之后会回复一个确认信号,在服务端接收到这个信号之后,服务端与客户端的通道也就关闭了 ==== 四、 实验原理 ==== * iCore3带有W5500嵌入式以太网控制器,本实验实现TCP客户端功能。以PC作为服务器,iCore3作为客户端,PC的IP地址192.168.0.2,端口号为60001,iCore3的IP地址为192.168.0.10,端口随机。当客户端连接到服务器,TCP建立成功即可进行数据信息传输。以下为实验原理图。 {{ :icore3:icore3_arm_hal_23_13.png?direct |}} ==== 五、 实验程序 ==== === 1. main()函数中建立的客户端程序 === while (1) { //处理TCP client信息 switch(getSn_SR(0)) /*获取socket0的状态*/ { case SOCK_INIT: /*socket初始化完成*/ connect(0, remote_ip ,60001); /*在TCP模式下向服务器发送连接请求*/ 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); /*len为已接收数据的大小*/ if(receive_length > 0) { memset(receive_buffer,0,sizeof(receive_buffer)); recv(0,receive_buffer,receive_length); /*W5500接收来自Sever的数据*/ send(0,receive_buffer,receive_length); } break; case SOCK_CLOSE_WAIT: /*socket等待关闭状态*/ disconnect(0); break; case SOCK_CLOSED: /*socket关闭*/ local_port = rand() % 10000 + 50000; socket(0,Sn_MR_TCP,local_port,Sn_MR_ND); /*打开socket0的一个端口*/ break; } } === 2. SPI初始化配置 === * 初始化SPI 主要是对SPI要使用到的引脚以及SPI通信协议中时钟相位和极性进行设置 void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; //SPI主模式 hspi1.Init.Direction = SPI_DIRECTION_2LINES; //全双工模式 hspi1.Init.DataSize = SPI_DATASIZE_8BIT; //数据位为8位 hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; //CPOL = 0 hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; //CPHA为数据线的第一个变化沿 hspi1.Init.NSS = SPI_NSS_SOFT; //软件控制NSS hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;//2分频 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; //最高位先发送 hspi1.Init.TIMode = SPI_TIMODE_DISABLE; //TIMODE模式关闭 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//CRC关闭 hspi1.Init.CRCPolynomial = 10;//默认值,无效 if (HAL_SPI_Init(&hspi1) != HAL_OK)//初始化 { Error_Handler(); } } === 3. SPI读写函数配置 === * HAL_SPI_TransmitReceive()为SPI的HAL库读写函数,一次操作一个字节,数据同时写入同时读出。send_data()函数为单字节读写函数,write()函数为多字节读写函数,可实现多字节数据的读写。 static unsigned char send_data(unsigned char data)//SPI读写字节函数 { unsigned char receive_data; HAL_SPI_TransmitReceive(&hspi1,&data,&receive_data,1,1000);//接收发送函数 return receive_data;//返回接收到的值 } static int write(int number, unsigned char * buf) //SPI读写多字节函数 { int i; SPI1_CS_OFF; //拉低CS引脚 for (i = 0; i < number; i++){ buf[i] = send_data(buf[i]); //调用send_data()函数 } SPI1_CS_ON; //拉高CS引脚 return 0; } === 4. W5500.c中的寄存器读写函数 === //定义本设备IP地址、默认网关、MAC地址、子网掩码 W5500_T w5500={ .initialize=initialize, .mac = {0x00,0x98,0xdc,0x42,0x61,0x11}, .ip = {192,168,0,10}, .sub = {255,255,255,0}, .gw = {192,168,0,1} }; //W5500写函数 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 } //W5500读函数 unsigned char IINCHIP_READ (unsigned long int addrbsb) // Address byte 1 { 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; } ==== 六、 实验步骤 ==== - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连); - 把iCore3(USB OTG)通过Micro USB线与计算机相连,为iCore3供电; - 把iCore3网口通过网线与计算机网口相连; - 设置本机电脑IP;(方法见附录1) - 打开Keil MDK 开发环境,并打开本实验工程; - 打开TCP&UDP测试工具;(安装及使用方法见附录2) - 烧写程序到iCore3上; - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。 ==== 七、 实验现象 ==== * 在发送区编辑完要发送的数据信息后,点击发送即可收到发送的数据包。如图所示 {{ :icore3:icore3_arm_hal_23_14.png?direct |}} ==== 附录1 ==== 1、打开控制面板网络和Internet网络和共享中心更改适配器设置以太网属性 {{ :icore3:icore3_arm_hal_23_14.png?direct |}} 2、Internet协议版本选择使用下面的IP地址(如下图所示),然后更改IP地址和默认网关 {{ :icore3:icore3_arm_hal_23_14.png?direct |}} ==== 附录2 ==== 1、TCP&UDP测试工具安装 双击TCPUDPDebug102_Setup.exe,点击下一步,在这里安装路径我们默认即可,点击安装,然后Finish。 2、TCP&UDP测试工具的使用 (1)打开测试工具,界面如下。点击创建服务器,弹出了设置端口的窗口,端口设置为60001。 {{ :icore3:icore3_arm_hal_23_14.png?direct |}} (2)服务器已经创建完成(如下图),点击启动服务器 {{ :icore3:icore3_arm_hal_23_14.png?direct |}} (3)iCore3客户端自动连接服务器,即可进行通信。(若连接不上请关闭电脑防火墙)