调通STM32F103RCT6 与W5500网卡芯片的PING程序


接到一个任务,验证硬件同事的一块板子上网卡芯片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



请先登录后发表评论
  • 最新评论
  • 总共0条评论