接到一个任务,验证硬件同事的一块板子上网卡芯片W5500的功能是否正常,MCU使用的是STM32F103RCT6 ,从了解到的信息看,W5500和MCU之间使用SPI接口进行通信,跟最近调了好久的DW1000的使用方法相同,驱动是厂家提供的,也就是只需要调通SPI通信,基本上就能驱动W5500工作!
标准库版本:STM32F10x_StdPeriph_Lib_V3.5.0
W5500与STM32F103RCT6 的引脚关系如下,使用的是STM32F103RCT6 芯片的SPI2:
PA8 -> W5500_RST PB12 -> W5500_SCS PB13 -> W5500_SCK PB14 -> W5500_MISO PB15 -> W5500_MOSI PA15 -> W5500_INT
关键的第一个点是GPIO的初始化(参考CSDN的文档实现):
GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; /*使能GPIOA的rcc时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /*配置GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_15| GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure SPI1 pins: SCK, MISO and MOSI -------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Set Chip Select pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_12); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA, GPIO_Pin_8);//RST /*配置GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*初始化GPIO*/ GPIO_Init(GPIOC, &GPIO_InitStructure); /* Set SPI interface */ SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode=SPI_Mode_Master; SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS=SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial=7; SPI_Init(SPI2,&SPI_InitStructure); SPI_Cmd(SPI2,ENABLE); SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_TXE); SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_RXNE);
W5500的上电,根据W5500的驱动文档,需要把W5500的RST引脚拉低超过500us
void func_w5500_reset(void) { GPIO_ResetBits(W5500_RST_GPIO_PORT, W5500_RST_PIN); delay_ms(2); GPIO_SetBits(W5500_RST_GPIO_PORT, W5500_RST_PIN); delay_ms(1600); }
SPI读写:
/* NSS pin is SW controllable */ #define port_SPIx_set_chip_select() GPIO_SetBits(W5500_SPI2_CS_GPIO_PORT, W5500_SPI2_CS_PIN) #define port_SPIx_clear_chip_select() GPIO_ResetBits(W5500_SPI2_CS_GPIO_PORT, W5500_SPI2_CS_PIN) uint8_t func_spi_write_a_byte(uint8_t byte) { //port_SPIx_set_chip_select(); /* Wait until TXE flag is set to send data */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) { } //SPI_I2S_SendData(SPI2, byte); SPI2->DR = byte; /* set output to 0 (MOSI), this is necessary for e.g. when waking up DW1000 from DEEPSLEEP via dwt_spicswakeup() function. */ /* Wait until RXNE flag is set to read data */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) { } //return SPI_I2S_ReceiveData(SPI2); uint8_t byte_read = SPI2->DR; //copy data read form (MISO) //port_SPIx_clear_chip_select(); return byte_read; } void func_spi_cs_select(void) { port_SPIx_clear_chip_select(); } void func_spi_cs_deselect(void) { port_SPIx_set_chip_select(); }
测试程序
#include "SEGGER_RTT.h" #define logD(...) SEGGER_RTT_printf(0, __VA_ARGS__) int main(void) { reset_w5500(); config_eth(); uint8_t test_0 = 0; uint8_t test_1 = 1; while(1) { int i; SEGGER_RTT_printf(0, "times:%d\r\n", times++); test_eth(); delay_ms(500); } } typedef uint8_t uint8; static uint8 test_ip[8] = {'\0'}; static char print_str[1024] = "\0"; void test_eth(){ int index = 0; memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getGAR(test_ip); index = 0; for(int i=0; i<4; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("gateway:%s\r\n", print_str); memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getSIPR(test_ip); index = 0; for(int i=0; i<4; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("ip:%s\r\n", print_str); } void config_eth(){ uint8 mac[6]={0, }; uint8 lip[4]={192,168,86,197}; uint8 sub[4]={255,255,255,0}; uint8 gw[4]={192,168,86,1};//根据网络所在的IP地址段和网关信息修改 char print_str[1024] = "\0"; memset(print_str, 0x00, 1024); memset(mac, 0x00, 6); getMacByLockCode(mac); int index = 0; for(int i=0; i<6; i++){ sprintf(print_str + index, "%d.", mac[i]); index = strlen(print_str); } logD("mac:%s\r\n", print_str); uint8 test_ip[8] = {'\0'}; memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getSIPR(test_ip); index = 0; for(int i=0; i<4; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("old ip:%s\r\n", print_str); setSHAR(mac); memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getSHAR(test_ip); index = 0; for(int i=0; i<6; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("new mac:%s\r\n", print_str); setSUBR(sub); setGAR(gw); setSIPR(lip); memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getGAR(test_ip); index = 0; for(int i=0; i<4; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("gateway:%s\r\n", print_str); memset(test_ip, 0x00, 8); memset(print_str, 0x00, 1024); getSIPR(test_ip); index = 0; for(int i=0; i<4; i++){ sprintf(print_str + index, "%d.", test_ip[i]); index = strlen(print_str); } logD("ip:%s\r\n", print_str); }
使用参考连接中提供的下载iolibarary,修改了基本的方法后,调通了ping程序
遗留问题:
STM32 CubeMX生成基于Hal库的工程,在SPI口配置为输出时,拉低和拉高均不生效;
参考文档:
https://blog.csdn.net/aliuguangjin/article/details/104552552
https://download.csdn.net/download/aliuguangjin/12197757
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com