上一篇忘了说了一个问题,那就是时钟,M4单片机采用的是168MHZ主频,所以这里的配置按照如下:
这是查芯片手册得来的,而到了H7主频则为400MHZ,需要换算一下,下面给出H7的FMC驱动程序,H7的单片机型号为STM32H743IITx:
基本上三部走:配置IO、配置MPU、配置FMC
/*
*********************************************************************************************************
*
* 模块名称 : ksz8851并口驱动
* 文件名称 : bsp_fmc_ksz8851.c
* 版 本 :
* 说 明 :
*
*
*********************************************************************************************************
*/
#include "stm32h7xx_hal.h"
#include "stm32h7xx_ll_fmc.h"
#include "bsp_fmc_ksz8851.h"
#include "ksz8851.h"
/* KSZ8851 的 GPIO :
PD0/FSMC_D2
PD1/FSMC_D3
PD4/FSMC_NOE
PD5/FSMC_NWE
PD8/FSMC_D13
PD9/FSMC_D14
PD10/FSMC_D15
PD14/FSMC_D0
PD15/FSMC_D1
PE7/FSMC_D4
PE8/FSMC_D5
PE9/FSMC_D6
PE10/FSMC_D7
PE11/FSMC_D8
PE12/FSMC_D9
PE13/FSMC_D10
PE14/FSMC_D11
PE15/FSMC_D12
PF0/FSMC_A0
PD7/FSMC_NE1 --- ksz8851_1片选主信号
PG9/FSMC_NE2 --- ksz8851_2片选主信号
*/
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKSZ8851
* 功能说明: 配置连接KSZ8851的GPIO和FSMC
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
NOR_HandleTypeDef eth1,eth2;
void bsp_Initfmc_ksz8851(void)
{
FMC_NORSRAM_TimingTypeDef ReadTiming;
FMC_NORSRAM_TimingTypeDef WriteTiming;
GPIO_InitTypeDef GPIO_InitStruct;
MPU_Region_InitTypeDef MPU_InitStruct;
/** Peripheral clock enable */
__HAL_RCC_FMC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9
| GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13
| GPIO_PIN_14 | GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
| GPIO_PIN_14 | GPIO_PIN_15
| GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/** Disable the MPU */
HAL_MPU_Disable();
/* 配置FMC驱动屏幕的MPU属性为Device或者Strongly Ordered */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = KSZ8851_BASE_A;
MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = KSZ8851_BASE_B;
MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
/* -- FSMC Configuration ------------------------------------------------------*/
WriteTiming.AddressSetupTime = 10U; /* 根据M4所配置时间,400MHz换算168MHz比例而来*/
WriteTiming.AddressHoldTime = 8U;
WriteTiming.DataSetupTime = 51U; /* 50个HLCK周期,125ns>100ns建立时间 */
WriteTiming.BusTurnAroundDuration = 0U;
WriteTiming.CLKDivision = 0U;
WriteTiming.DataLatency = 0U;
WriteTiming.AccessMode = FMC_ACCESS_MODE_A;
ReadTiming.AddressSetupTime = 10U; /* 根据M4所配置时间,400MHz换算168MHz比例而来*/
ReadTiming.AddressHoldTime = 8U;
ReadTiming.DataSetupTime = 51U; /* 50个HLCK周期,125ns>100ns建立时间 */
ReadTiming.BusTurnAroundDuration = 0U;
ReadTiming.CLKDivision = 0U;
ReadTiming.DataLatency = 0U;
ReadTiming.AccessMode = FMC_ACCESS_MODE_A;
eth1.Instance = FMC_NORSRAM_DEVICE;
eth1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/** hsram2.Init */
eth1.Init.NSBank = FMC_NORSRAM_BANK1; /** 选择设置的BANK及片选信号 */
eth1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; /** 设置是否数据地址总线分时复用 */
eth1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; /** 设置存储器类型 */
eth1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16; /** FMC_MemoryDataWidth_16b; 设置数据宽度 */
eth1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; /** 设置是否采用并发访问模式 */
eth1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; /** 设置wait信号有效电平 */
eth1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; /** 设置wait信号有效时机 */
eth1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; /** 设置是否使能写操作 */
eth1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; /** 设置是否使用wait信号 */
eth1.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE; /** 设定是否使用单独的写时序 */
eth1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
eth1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; /** 设定是否使用写并发模式 */
eth1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;/** FMC_CONTINUOUS_CLOCK_SYNC_ONLY; */
eth1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;/** FMC_WRITE_FIFO_ENABLE; */
eth1.Init.PageSize = FMC_PAGE_SIZE_NONE;
eth2.Instance = FMC_NORSRAM_DEVICE;
eth2.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/** hsram2.Init */
eth2.Init.NSBank = FMC_NORSRAM_BANK2; /** 选择设置的BANK及片选信号 */
eth2.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; /** 设置是否数据地址总线分时复用 */
eth2.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; /** 设置存储器类型 */
eth2.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16; /** FMC_MemoryDataWidth_16b; 设置数据宽度 */
eth2.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; /** 设置是否采用并发访问模式 */
eth2.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; /** 设置wait信号有效电平 */
eth2.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; /** 设置wait信号有效时机 */
eth2.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; /** 设置是否使能写操作 */
eth2.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; /** 设置是否使用wait信号 */
eth2.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE; /** 设定是否使用单独的写时序 */
eth2.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
eth2.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; /** 设定是否使用写并发模式 */
eth2.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;/** FMC_CONTINUOUS_CLOCK_SYNC_ONLY; */
eth2.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;/** FMC_WRITE_FIFO_ENABLE; */
eth2.Init.PageSize = FMC_PAGE_SIZE_NONE;
if (HAL_NOR_Init(ð1, &ReadTiming, &WriteTiming) != HAL_OK)
{
while (1)
{}
}
else
{}
if (HAL_NOR_Init(ð2, &ReadTiming, &WriteTiming) != HAL_OK)
{
while (1)
{}
}
else
{}
}
/* ************************************************* (END OF FILE) *********************************/
然后就是初始化8851使用了
bsp_Initfmc_ksz8851(); /* 初始化KSZ8851并口*/
ksz8851_init(); /* ksz8851初始化*/
void ksz8851_init(void)
{
GPIO_Config();
EXTILine_Config(); /* */
KSZ8851_Reset();
uint8 ok = 0;
if (ksz8851_init_b() != NULL_)
{
ok++;
}
else
{
}
if (ksz8851_init_a() != NULL_)
{
ok++;
}
else
{
}
}
多干了一些事情,关于8851外部控制引脚的配置
const static S_GpioCtrl KSZ8851_RESET[2] =
{
{RCC_AHB4ENR_GPIOGEN, GPIOG, GPIO_PIN_2},
{RCC_AHB4ENR_GPIODEN, GPIOD, GPIO_PIN_13}
};
const static S_GpioCtrl KSZ8851_PME[2] =
{
{RCC_AHB4ENR_GPIOGEN, GPIOG, GPIO_PIN_3},
{RCC_AHB4ENR_GPIODEN, GPIOD, GPIO_PIN_12}
};
static void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOG clock */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
GPIO_InitStructure.Pin = (uint32)(KSZ8851_RESET[0].GPIOxPinx);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KSZ8851_RESET[0].GPIOx, &GPIO_InitStructure);
GPIO_InitStructure.Pin = (uint32)(KSZ8851_RESET[1].GPIOxPinx);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KSZ8851_RESET[1].GPIOx, &GPIO_InitStructure);
GPIO_InitStructure.Pin = (uint32)(KSZ8851_PME[0].GPIOxPinx);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KSZ8851_PME[0].GPIOx, &GPIO_InitStructure);
GPIO_InitStructure.Pin = (uint32)(KSZ8851_PME[1].GPIOxPinx);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(KSZ8851_PME[1].GPIOx, &GPIO_InitStructure);
}
static void KSZ8851_Reset(void)
{
//复位
HAL_GPIO_WritePin(KSZ8851_RESET[0].GPIOx, KSZ8851_RESET[0].GPIOxPinx,0);
HAL_GPIO_WritePin(KSZ8851_RESET[1].GPIOx, KSZ8851_RESET[1].GPIOxPinx,0);
DelayMs(20);
HAL_GPIO_WritePin(KSZ8851_RESET[0].GPIOx, KSZ8851_RESET[0].GPIOxPinx,1);
HAL_GPIO_WritePin(KSZ8851_RESET[1].GPIOx, KSZ8851_RESET[1].GPIOxPinx,1);
//设置为非电源唤醒状态
HAL_GPIO_WritePin(KSZ8851_PME[0].GPIOx, KSZ8851_PME[0].GPIOxPinx,1);
HAL_GPIO_WritePin(KSZ8851_PME[1].GPIOx, KSZ8851_PME[1].GPIOxPinx,1);
}
/*
*********************************************************************************************************
* 函 数 名: EXTILine8_Config
* 功能说明: 初始化外部中断,用到的外部中断有PG4-ENET1, PD11-ENET2
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void EXTILine_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOG clock */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* Enable SYSCFG clock */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* Configure PG15 pin as input floating */
GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = (uint32)(GPIO_PIN_4);
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_InitStructure.Pin = (uint32)(GPIO_PIN_11);
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
}
8851初始化还有一部分函数贴出来
void * ksz8851_init_a(void)
{
uint32 i;
memset((void *)&ksz8851_a, 0, sizeof(S_BOARD_INFO));
for (i= 0U; i<LEP_MAC_ADDR_LEN; i++) /* */
{
ksz8851_a.mac_addr[i] = MC_MACA[i];
}
ksz8851_a.phw_addr = (uint16 IO__ *)KSZ8851_BASE_A;
ksz8851_a.phw_addr_cmd = (uint16 IO__ *)KSZ8851_A_CMD;
if (ks8851_probe(&ksz8851_a) == 0) /* */
{
ks_net_open(&ksz8851_a);
return (void *)&ksz8851_a; /* search board and register */
}
else
{
return NULL_;
}
}
/*
*********************************************************************************************************
* 函 数 名: ksz8851_init_b
* 功能说明: 8851_b 初始化
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void * ksz8851_init_b(void)
{
uint32 i;
memset((void *)&ksz8851_b, 0, sizeof(S_BOARD_INFO));
for (i= 0U; i<LEP_MAC_ADDR_LEN; i++) /* */
{
ksz8851_b.mac_addr[i] = MC_MACB[i];
}
ksz8851_b.phw_addr = (uint16 IO__ *)KSZ8851_BASE_B;
ksz8851_b.phw_addr_cmd = (uint16 IO__ *)KSZ8851_B_CMD;
if (ks8851_probe(&ksz8851_b) == 0) /* */
{
ks_net_open(&ksz8851_b);
return (void *)&ksz8851_b; /* search board and register */
}
else
{
return NULL_;
}
}