完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
w5500就是一个以太网模块,这个模块本身集成了tcp/ip协议,mcu只需要通过spi协议读写他的寄存器就可以进行数据交互了,
下面大致说说stm32移植w5500的过程和步骤吧, 10个引脚中,真正使用的也就只有vcc gnd miso mosi sclk scs 这几个脚,RST和int引脚如果是引用官方的库的话,是不需要的(RST是复位引脚,INT是中断触发引脚) 移植W5500大致分为下面的几个步骤
因为W5500模块内部自己实现了TCP/IP协议,所以我们在外部只需要通过他提供的接口把相关的参数传递进去就行了,比如物理地址,本机IP,本机端口,目标端口,目标IP等等, 而模块提供的是一个SPI的数据接口 下面是103的SPI初始化代码 //ÒÔÏÂÊÇSPIÄ£¿éµÄ³õʼ»¯´úÂ룬ÅäÖóÉÖ÷»úģʽ£¬·ÃÎÊSD Card/W25Q64/NRF24L01 //SPI¿Ú³õʼ»¯ //ÕâÀïÕëÊǶÔSPI1µÄ³õʼ»¯ void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; // RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTBʱÖÓʹÄÜ // RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );//SPI2ʱÖÓʹÄÜ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15¸´ÓÃÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOB GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PB13/14/15ÉÏÀ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //ÉèÖÃSPIµ¥Ïò»òÕßË«ÏòµÄÊý¾Ýģʽ:SPIÉèÖÃΪ˫ÏßË«ÏòÈ«Ë«¹¤ SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //ÉèÖÃSPI¹¤×÷ģʽ:ÉèÖÃΪÖ÷SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //ÉèÖÃSPIµÄÊý¾Ý´óС:SPI·¢ËͽÓÊÕ8λ֡½á¹¹ // SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //ʱÖÓÐü¿ÕµÍ // SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //Êý¾Ý²¶»ñÓÚµÚ1¸öʱÖÓÑØ SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //´®ÐÐͬ²½Ê±ÖӵĿÕÏÐ״̬Ϊ¸ßµçƽ SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //´®ÐÐͬ²½Ê±Öӵĵڶþ¸öÌø±äÑØ£¨ÉÏÉý»òϽµ£©Êý¾Ý±»²ÉÑù SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSSÐźÅÓÉÓ²¼þ£¨NSS¹Ü½Å£©»¹ÊÇÈí¼þ£¨Ê¹ÓÃSSI룩¹ÜÀí:ÄÚ²¿NSSÐźÅÓÐSSIλ¿ØÖÆ SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//²¨ÌØÂÊÔ¤·ÖƵֵ:²¨ÌØÂÊÔ¤·ÖƵֵΪ256 ³õʼ»¯Ê±Îª×îµÍËÙģʽ SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //Ö¸¶¨Êý¾Ý´«Êä´ÓMSBλ»¹ÊÇLSBλ¿ªÊ¼:Êý¾Ý´«Êä´ÓMSBλ¿ªÊ¼ SPI_InitStructure.SPI_CRCPolynomial = 7; //CRCÖµ¼ÆËãµÄ¶àÏîʽ SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); //ʹÄÜSPIÍâÉè // SPI1_ReadWriteByte(0xff);//Æô¶¯´«Êä } //SPI ËÙ¶ÈÉèÖú¯Êý //SpeedSet: //SPI_BaudRatePrescaler_2 2·ÖƵ //SPI_BaudRatePrescaler_8 8·ÖƵ //SPI_BaudRatePrescaler_16 16·ÖƵ //SPI_BaudRatePrescaler_256 256·ÖƵ void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler) { assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); SPI1->CR1&=0XFFC7; SPI1->CR1|=SPI_BaudRatePrescaler; //ÉèÖÃSPIËÙ¶È SPI_Cmd(SPI1,ENABLE); } 2,初始化GPIO 除去SPI口之外还有一个片选引脚SCS,这个引脚很重要,在官方协议实现的4个函数中,起到的很关键的作用,我的开发板上这个引脚是放到了PA0上,下面是初始化代码 void W5500_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); // ???????SPI-CS?? (PA0) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_0); } 3,下载官方库代码, 官方库代码分为三个部分
如果只需要实现基本的tcp,udp协议只需要移植1就可以了,如果想要DHCP来自动获取本地IP,就需要把DHCP添加进去,如果要实现域名解析就需要DNS协议,也已实现部分也可以全部实现,下面会讲解具体的实现步骤和函数用法 socket.c 文件夹里面主要是socket的一些函数,比如close connect socket等等函数,实现了一些应用层的封装 w5500.c 文件主要实现的是对W5500模块寄存器的读写和操作,包括读写那些寄存器,地址是多少等等, wizchip_conf.c 就是一个公共文件主要包括和SPI的连接以及连接W5500读写寄存器函数和socket函数。 DHCP.c 主要就是初始化DHCP,启动DHCP,获取ip,端口等函数 DNS.c 主要也就是一个初始化函数,一个获取函数,还有一个hande函数 以上的具体使用下面再说 4,添加文件到工程 这个比较简单,如果是使用的keil,直接把文件添加进去,然后c/c++ 下面的include path添加相应的目录就可以了 5,实现SPI和库文件对接 前面说了库文件wizchip_conf.c 里面就包括了和SPI口的对接实现函数,其实也就是一个函数指针, 在spi里实现一些函数,然后把函数名赋值给wizchip_conf.c里面的一些函数指针,这样W5500.c里面的函数实现读写的时候,就能够直接使用SPI接口了, 具体实现的函数有以下6个函数名可以自己随便改,这个不重要 void SPI1_WriteByte(u8 TxData) u8 SPI1_ReadByte() void SPI_CrisEnter(void) void SPI_CrisExit(void) void SPI_CS_Select(void) void SPI_CS_Deselect(void) 实现了这几个函数之后,需要把他们注册到库函数里面(也就是把函数指针赋值给别人调用) 官方提供了一串代码 void register_wizchip() { // First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP /* Critical section callback */ reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit); /* Chip selection call back */ reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect); /* SPI Read & Write callback function */ reg_wizchip_spi_cbfunc(SPI1_ReadByte, SPI1_WriteByte); } 这个函数是我自己包含的,官方提供的代码里面还包含一些宏定义,不过被我干掉了 在初始化函数调用这个函数之后,就把SPI接口的函数传递给库了,这样库在调用读写的时候,就能够正常读写了 下面是上面 几个函数的实现代码 //SPIx ¶Áдһ¸ö×Ö½Ú //TxData:ҪдÈëµÄ×Ö½Ú //·µ»ØÖµ:¶ÁÈ¡µ½µÄ×Ö½Ú void SPI1_WriteByte(u8 TxData) { while((SPI1->SR&SPI_I2S_FLAG_TXE)==0); //?????? SPI1->DR=TxData; //????byte while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //???????byte SPI1->DR; } u8 SPI1_ReadByte() { while((SPI1->SR&SPI_I2S_FLAG_TXE)==0); //?????? SPI1->DR=0xFF; //???????????????? while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //???????byte return SPI1->DR; } /** * @brief ????? * @retval None */ void SPI_CrisEnter(void) { __set_PRIMASK(1); } /** * @brief ????? * @retval None */ void SPI_CrisExit(void) { __set_PRIMASK(0); } /** * @brief ????????? * @retval None */ void SPI_CS_Select(void) { GPIO_ResetBits(GPIOA,GPIO_Pin_0); } /** * @brief ????????? * @retval None */ void SPI_CS_Deselect(void) { GPIO_SetBits(GPIOA,GPIO_Pin_0); } PS,这里说一下,SPI的读写函数,有很多种写法,但是我测试过后发现,就这种是好的,具体原因不晓得,可能和库函数读写的时序有关,其他的的读写方式单独使用的时候都是好的,但是添加到库里面就不行了 PPS,上面的GPIO_0 就是上面说的SCS接口,按照自己开发板写就好了 6,调用函数接口实现TCP客户端的实现 官方提供了3个函数,分别是建立tcp,UDP,和tcp server,如果不移植DHCP协议,用户只需要填写本机IP地址和目标IP地址和目标端口以及,选择0~7的其中一条链路 三个具体的函数我就不放了,放一个github的连接把 以建立一个TCP客户端为例子说明一下函数调用的流程
下面是DHCP的实现方向 1,添加DHCP文件到工程 这个貌似没啥好说的 2,对DHCP进行初始化代码如下 uint8_t memsize[2][8] = { {2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}}; if(ctlwizchip(0,(void*)memsize) == -1){ printf("WIZCHIP Initialized fail.rn"); while(1); } setSHAR(gWIZNETINFO.mac); DHCP_init(0,buff); reg_dhcp_cbfunc(my_ip_assign, my_ip_assign, my_ip_conflict); uint8_t dhcp_ret = DHCP_run(); while(dhcp_ret != DHCP_IP_LEASED) { delay_ms(500); dhcp_ret = DHCP_run(); } 第一步是初始化ctlwizchip函数, 第二部是设置mac地址,可以放到别的地方或者改变顺序, 第三部是初始化DHCP,buff就是一个数组 第三部是初始化reg_dhcp_cbfunc函数,他实现的两个函数分别是 void my_ip_assign(void) { getIPfromDHCP(gWIZNETINFO.ip); getGWfromDHCP(gWIZNETINFO.gw); getSNfromDHCP(gWIZNETINFO.sn); getDNSfromDHCP(gWIZNETINFO.dns); gWIZNETINFO.dhcp = NETINFO_DHCP; /* Network initialization */ network_init(); // apply from dhcp //这是我自己实现的,内部的实现函数就是 // ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO); printf("DHCP LEASED TIME : %d Sec.rn", getDHCPLeasetime()); } void my_ip_conflict(void) { printf("CONFLICT IP from DHCPrn"); //halt or reset or any... while(1); // this example is halt. } 第四部就是运行run函数,并且等待ip地址获取成功,也就是返回码等待4,DHCP_IP_LEASED,在一个贴吧里面看到有个哥们给的代码是success,不知道为啥,我下载的库里面没有和这个枚举,测试了很久发现是等于4的时候是正常的之后就可以在mian里面进行读写处理了, DNS其实很简单,就两个函数,一个是DNS_init初始化,一个是int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); 这个函数的三个参数,文档上也有写 /*返回1是代表成功了, dns_ip是dns服务器的ip地址,这个随便百度一个就可以了 name是我们需要解析的域名,比如www.baidu.com ip_from_dns是返回的指针数据,也就是www.baidu.com的ip地址 DNS最典型的运用是PC的时候的ping 如果没有DNS的话是没有办法直接连接百度的服务器的,只有通过DNS服务器解析之后,获取到百度的IP之后,才能正常的使用 下面是我百度到的几个DNS服务器ip地址, OneDNS (112.124.47.27) OpenerDNS(42.120.21.30) BaiduDNS (180.76.76.76) aliDNS (223.5.5.5, 223.6.6.6) 114DNS (114.114.114.114, 114.114.115.115) 114DNS安全版 (114.114.114.119, 114.114.115.119) 114DNS家庭版 (114.114.114.110, 114.114.115.110) Dns派:电信/移动/铁通 (101.226.4.6, 218.30.118.6) Dns派:联通 (123.125.81.6, 140.2 07.198.6) 好久没写,算是做个开始把 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
568浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 14:31 , Processed in 0.791246 second(s), Total 74, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号