|**银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801** ||| |技术支持邮件|Gingko@vip.163.com ||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-09-16 | gingko | 初次建立 | \\ \\ \\ \\ \\ ===== STM32CubeMX教程二十五——LAN_UDP实验 ===== 1. 新建工程:在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR {{ :icore3:icore3_cube_25_1.png?direct | }} 2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32F407IGTx。 {{ :icore3:icore3_cube_25_2.png?direct | }} 3. 配置RCC,使用外部时钟源 {{ :icore3:icore3_cube_25_3.png?direct | }} 4. 配置调试引脚 {{ :icore3:icore3_cube_25_4.png?direct | }} 5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output {{ :icore3:icore3_cube_25_5.png?direct | }} 6. 引脚模式配置 {{ :icore3:icore3_cube_25_6.png?direct | }} 7. 选中SPI1,Mode选择Full_Duplex Master,配置PB3(SPI1_SCK)、PB4(SPI1_MISO)、PA7(SPI1_MOSI)和PA15(CS)为SPI引脚。 {{ :icore3:icore3_cube_25_7.png?direct | }} 配置PA15(CS)的GPIO输出模式 {{ :icore3:icore3_cube_25_8.png?direct | }} 8. 时钟源设置,选择外部高速时钟源,配置为最大主频 {{ :icore3:icore3_cube_25_9.png?direct | }} 9. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK5 {{ :icore3:icore3_cube_25_10.png?direct | }} 10. 点击Code Generator,进行进一步配置 {{ :icore3:icore3_cube_25_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_25_12.png?direct | }} 创建成功,打开工程。 \\ \\ \\ \\ ===== 实验二十五:LAN_UDP实验——以太网数据传输 ===== ==== 一、 实验目的与意义 ==== - 了解STM32 的SPI和W5500的UDP结构 - 了解STM32 的SPI和W5500的UDP特征 - 掌握STM32 HAL库中SPI和UDP的配置方法 - 掌握STM32CubeMX的使用方法 - 掌握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_25_1.png?direct |}} * 在一个SPI时钟周期内,会完成如下操作: - 主设备通过MOSI线发送1位数据,从设备通过该线读取这1位数据; - 从设备通过MISO线发送1位数据,主设备通过该线读取这1位数据。 * 这是通过移位寄存器来实现的。主机和从机都有一个串行移位寄存器,随着时钟脉冲,数据按照从高位到低位的方式依次移出主设备寄存器和从机寄存器,并且依次移入从设备寄存器和主设备寄存器。当寄存器中的内容全部移出时,相当于完成了两个寄存器内容的交换。 * 主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。寄存器通过MOSI信号线将字节传送给主机,从机也将自己的移位寄存器中的内容通过MISO信号线返回给主机,这样两个移位寄存器中的内容就被交换,外设的写操作和读操作是同时进行的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。 {{ :icore3:icore3_arm_hal_25_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_25_3.png?direct |}} {{ :icore3:icore3_arm_hal_25_4.png?direct |}} {{ :icore3:icore3_arm_hal_25_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_25_6.png?direct |}} * SUBR (子网掩码寄存器) [R/W] [0x0005 – 0x0008] [0x00] * 该寄存器用来设置子网掩码地址,例如“255.255.255.0”。 {{ :icore3:icore3_arm_hal_25_7.png?direct |}} * SHAR (源 MAC 地址寄存器) [R/W] [0x0009 – 0x000E] [0x00] * 该寄存器用来设置源 MAC 地址。例如: “00.08.DC.01.02.03”。 {{ :icore3:icore3_arm_hal_25_8.png?direct |}} * SIPR (源 IP 地址寄存器) [R/W] [0x000F – 0x0012] [0x00] * 该寄存器用来设置源 IP 地址。例如: “192.168.0.2”。 {{ :icore3:icore3_arm_hal_25_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_25_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_25_11.png?direct |}} === 3、UDP简介 === * UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。 * UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。 * UDP 协议具备以下特点: * 没有各种连接:在传输数据前不需要建立连接,也避免了后续的断开连接。 * 不重新排序:对到达顺序混乱的数据包不进行重新排序。 * 没有确认:发送数据包无须等待对方确认。因此,使用 UDP 协议可以随时发 * UDP通信流程图如下: {{ :icore3:icore3_arm_hal_25_12.png?direct |}} ==== 四、 实验原理 ==== * iCore3带有W5500嵌入式以太网控制器,本实验实现UDP功能。PC的IP地址192.168.0.2, iCore3的IP地址为192.168.0.10,端口号为30000。上电即可进行数据信息传输。以下为实验原理图。 {{ :icore3:icore3_arm_hal_25_13.png?direct |}} * iCore3双核心板CPU采用STM32F407IGT6,STM32F407通过SPI接口与W5500通信,来进行W5500寄存器的访问,从而进行IP地址、MAC地址、网关信息、子网掩码地址等信息的读写。同时通过SPI驱动W5500建立Socket通信,来进行UDP连接。 ==== 五、 实验程序 ==== === 1. main()函数中建立的服务器程序 === * W5500的UDP建立过程也是非常方便的,通过简单的读写寄存器便可以轻松实现。程序初始化完成以后,进入主循环函数。当Socket处于关闭状态时,在进行通信之前,我们先将该UDP模式的Socket端口初始化。当socket将处于 初始化完成状态即SOCK_UDP状态,此时就可以通过广播方式发送数据了。在测试之前要注意两个问题,首先建议关闭PC的防火墙;其次,若W5500模块与PC直接通过网线连接,需要修改PC的IP地址为静态IP,且保持与W5500的IP在 同一个网段;如果直接连接路由器,可以不用修改PC的IP地址。 while (1) { switch(getSn_SR(0)) /*获取socket0的状态*/ { case SOCK_UDP: if(getSn_IR(0) & Sn_IR_RECV) { setSn_IR(0, Sn_IR_RECV); } if((receive_length = getSn_RX_RSR(0))>0) /*receive_length为已接收数据长度*/ { length = recvfrom(0, receive_buffer, receive_length, pc_ip,&pc_port); /*接收数据*/ sendto(0, receive_buffer,length, pc_ip, pc_port); /*发送接收到的数据*/ } break; case SOCK_CLOSED: /*socket关闭*/ socket(0,Sn_MR_UDP,30000,0); /*打开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网口通过网线与计算机网口相连; - 打开Keil MDK 开发环境,并打开本实验工程; - 打开TCP&UDP测试工具;(安装及使用方法见附录) - 烧写程序到iCore3上; - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。 ==== 七、 实验现象 ==== * 在发送区编辑完要发送的数据信息后,点击发送即可收到发送的数据包。如图所示 {{ :icore3:icore3_arm_hal_25_14.png?direct |}} ==== 附录 ==== * 1、TCP&UDP测试工具安装 双击TCPUDPDebug102_Setup.exe,点击下一步,在这里安装路径我们默认即可,点击安装,然后Finish。 * 2、TCP&UDP测试工具的使用 (1)打开测试工具,界面如下。点击创建服务器,弹出了设置端口的窗口,端口设置为30000。 {{ :icore3:icore3_arm_hal_25_15.png?direct |}} (2)点击创建,创建完成即可通信。(若连接不上请关闭电脑防火墙)