w5500就是一个以太网模块,这个模块本身集成了tcp/ip协议,mcu只需要通过spi协议读写他的寄存器就可以进行数据交互了, 下面大致说说stm32移植w5500的过程和步骤吧, 移植W5500大致分为下面的几个步骤
1,初始化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 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,下载官方库代码,
我上面提供的百度网盘中包括1,2,3和帮助文档CHM 4,添加文件到工程 5,实现SPI和库文件对接 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的读写函数,有很多种写法,但是我测试过后发现,就这种是好的,具体原因不晓得,可能和库函数读写的时序有关,其他的的读写方式单独使用的时候都是好的,但是添加到库里面就不行了 6,调用函数接口实现TCP客户端的实现 官方提供了3个函数,分别是建立tcp,UDP,和tcp server,如果不移植DHCP协议,用户只需要填写本机IP地址和目标IP地址和目标端口以及,选择0~7的其中一条链路 三个具体的函数我就不放了,放一个github的连接把 以建立一个TCP客户端为例子说明一下函数调用的流程
使用了loopback_tcpc函数之后,tcp的连接完全不用我们管,因为他会读取W5500的寄存器自己再连接, 下面是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.\r\n'); 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函数, 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.\r\n', getDHCPLeasetime());}void my_ip_conflict(void){ printf('CONFLICT IP from DHCP\r\n'); //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最典型的运用是PC的时候的ping 如果没有DNS的话是没有办法直接连接百度的服务器的,只有通过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.207.198.6)
好久没写,算是做个开始把 |
|
来自: goodwangLib > 《STM32》