STM32H743+RT-Thread驱动SPI转网口DM9051模块进行联网

1. 使用RT-Thread Studio软件进行开发

STM32H743+RT-Thread驱动SPI转网口DM9051模块进行联网_第1张图片

使能SPI组件,使能lwip组件

2.修改drv_dm9051_init.c 初始化部分,增加SPI总线挂载设备的代码。

static int dm9051_auto_init(void)
{
    rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_4);
    dm9051_probe(DM9051_SPI_DEVICE, DM9051_DEVICE_NAME, DM9051_RST_PIN, DM9051_INT_PIN);

    return 0;
}
//INIT_ENV_EXPORT(dm9051_auto_init);

#include 
MSH_CMD_EXPORT(dm9051_auto_init, dm9051_auto_init);

3. 使用STM32CubeMX生成系统时钟配置代码与SPI1相关GPIO初始化的代码并放在board.c下面:

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 300;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

4. 修改drv_clk.c使得系统时钟为STM32Cubemx生成的时钟配置:

void clk_init(char *clk_source, int source_freq, int target_freq)
{
    //system_clock_config(target_freq);
    extern void SystemClock_Config(void);
    SystemClock_Config();
}
修改drv_dm9051.c
int dm9051_probe(const char *spi_dev_name, const char *device_name, int rst_pin, int int_pin)
{
    struct rt_dm9051_eth *eth;
    uint32_t device_id;

    struct rt_spi_device *spi_device = RT_NULL;

    spi_device = (struct rt_spi_device *)rt_device_find(spi_dev_name);
    spi_device->bus->owner = spi_device;
 //此步骤为必须步骤,不然SPI设备不能正常配置
    if (spi_device == RT_NULL)
    {
        LOG_E("[%s:%d] spi device %s not found!.", __FUNCTION__, __LINE__, spi_dev_name);
        return -RT_ENOSYS;
    }

    /* config spi */
    {
        struct rt_spi_configuration cfg;
        cfg.data_width = 8;
        cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
        cfg.max_hz = DM9051_SPI_MAX_HZ;               /* defaut=20M, max 50M  */
        if(spi_device->bus->owner == RT_NULL)
        {
            rt_kprintf("RT_OK\r\n");
        }
        rt_kprintf("owner= %d\r\n",*(spi_device->bus->owner));
        rt_spi_configure(spi_device, &cfg);
    }
    dm9051_chip_reset(spi_device);
//此步骤为必须步骤,不然读不到设备ID
    //rt_thread_mdelay(100);
    device_id  = DM9051_read_reg(spi_device, DM9051_VIDL);
    device_id |= DM9051_read_reg(spi_device, DM9051_VIDH) << 8;
    device_id |= DM9051_read_reg(spi_device, DM9051_PIDL) << 16;
    device_id |= DM9051_read_reg(spi_device, DM9051_PIDH) << 24;
    LOG_I("[%s L%d] device_id: %08X", __FUNCTION__, __LINE__, device_id);

    if(device_id != DM9051_ID)
    {
        return -1;
    }

    device_id  = DM9051_read_reg(spi_device, DM9051_CHIPR);
    LOG_I("[%s L%d] CHIP Revision: %02X", __FUNCTION__, __LINE__, device_id);

    eth = rt_calloc(1, sizeof(struct rt_dm9051_eth));
    if(!eth)
    {
        return -1;
    }

    eth->spi_device = spi_device;
    eth->rst_pin = rst_pin;
    eth->int_pin = int_pin;

    /* OUI 00-60-6E Davicom Semiconductor, Inc. */
    eth->dev_addr[0] = 0x00;
    eth->dev_addr[1] = 0x60;
    eth->dev_addr[2] = 0x6E;
    eth->dev_addr[3] = 12;
    eth->dev_addr[4] = 34;
    eth->dev_addr[5] = 56;

    rt_pin_mode(eth->int_pin, PIN_MODE_INPUT_PULLDOWN);
    device_id = rt_pin_attach_irq(eth->int_pin, PIN_IRQ_MODE_RISING, dm9051_isr, eth); /* default: push-pull, high active. PIN_IRQ_MODE_HIGH_LEVEL or PIN_IRQ_MODE_RISING */
    LOG_D("[%s L%d] rt_pin_attach_irq #%d res:%d \n", __FUNCTION__, __LINE__, eth->int_pin, device_id);

    /* init rt-thread device struct */
    eth->parent.parent.type = RT_Device_Class_NetIf;
#ifdef RT_USING_DEVICE_OPS
    eth->parent.parent.ops = &dm9051_ops;
#else
    eth->parent.parent.init    = dm9051_init;
    eth->parent.parent.open    = dm9051_open;
    eth->parent.parent.close   = dm9051_close;
    eth->parent.parent.read    = dm9051_read;
    eth->parent.parent.write   = dm9051_write;
    eth->parent.parent.control = dm9051_control;
#endif /* RT_USING_DEVICE_OPS */

    /* init rt-thread ethernet device struct */
    eth->parent.eth_rx  = dm9051_rx;
    eth->parent.eth_tx  = dm9051_tx;

    rt_mutex_init(&eth->lock, "dm9051", RT_IPC_FLAG_FIFO);
    rt_timer_init(&eth->timer, "dm9051", dm9051_timeout, eth, RT_TICK_PER_SECOND/2, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);

    dm9051_monitor = eth;
    eth_device_init(&eth->parent, "e0");

    return 0;
}

至此,DM9051芯片已经能正常驱动,给设备插上网线后,dhcp会自动获取IP地址,通过PC端可以Ping通设备。

你可能感兴趣的:(stm32,单片机,arm)