当前位置: 首页 > news >正文

STM32F107单片机驱动Dp83848以太网芯片程序 项目开发用到了Dp83848这一个以...

STM32F107单片机驱动Dp83848以太网芯片程序 项目开发用到了Dp83848这一个以太网芯片,本人发现其配置起来比较麻烦,所以整理了一份STM32F107单片机驱动Dp83848的程序代码例程,方便大家学习相关代码的配置

最近在项目里折腾STM32F107和DP83848这对搭档,这PHY芯片配置起来真是让人头大。特别是当硬件同事把原理图甩过来的时候,看到那一堆MDIO/MDC信号线就预感到要掉头发。好在最后摸清了套路,这里把关键代码和踩坑经验分享给大家。

先说硬件接法,DP83848的PHYAD0引脚决定了PHY地址。咱们板子上这个引脚接地,所以PHY地址是0x00。这个地址后面配置MAC的时候要特别注意,很多兄弟在这里栽跟头。

STM32F107单片机驱动Dp83848以太网芯片程序 项目开发用到了Dp83848这一个以太网芯片,本人发现其配置起来比较麻烦,所以整理了一份STM32F107单片机驱动Dp83848的程序代码例程,方便大家学习相关代码的配置

上电第一步得先伺候好时钟。STM32的AHB总线时钟要开启,别忘了MAC用的DMA时钟:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);

接下来是GPIO配置。以RMII接口为例,注意CR寄存器要配置成50MHz模式:

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; // RMII_TXD0/TXD1 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);

PHY初始化这块最磨人。建议先用软件复位打个招呼:

uint16_t phy_status; ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_REG_BMCR, PHY_Reset); do { phy_status = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_REG_BMCR); } while (phy_status & PHY_Reset); // 等复位完成

然后开启自动协商,这里有个坑——DP83848的自动协商完成标志位有点迟钝,实测要加个延时:

ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_REG_BMCR, PHY_AutoNegotiation); HAL_Delay(1500); // 不睡够时间直接读状态会扑街 do { phy_status = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_REG_BMSR); } while (!(phy_status & PHY_AutoNego_Complete));

链路状态检测建议用中断方式。配置PHY的中断引脚接到STM32的某个EXTI:

// 开启链接状态变化中断 ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_REG_MISR, PHY_Link_Status_Interrupt); // 配置EXTI中断回调 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == PHY_INT_PIN) { uint16_t status = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_REG_MISR); if(status & PHY_Link_Status_Interrupt) { // 处理链接状态变化 handle_network_event(); } } }

MAC层的DMA描述符配置是个精细活,这里给个发送描述符的初始化示例:

ETH_DMADESCTypeDef *dma_tx_desc; dma_tx_desc = ETH_GetDMATxDesc(); for(int i=0; i<TX_DESC_COUNT; i++) { dma_tx_desc->Status = ETH_DMATXDESC_OWN; // 告诉DMA可以接管 dma_tx_desc->Buffer1Addr = (uint32_t)&tx_buffer[i][0]; if(i == TX_DESC_COUNT-1) { dma_tx_desc->Status |= ETH_DMATXDESC_RER; // 环回配置 } dma_tx_desc = (ETH_DMADESCTypeDef*)(dma_tx_desc->Buffer2NextDescAddr); }

最后上主程序骨架。建议先做个链路检测再启动协议栈:

int main(void) { hardware_init(); phy_init(); while(1) { if(ETH_CheckLink() == ETH_LINK_UP) { // 亮个绿灯表示联网成功 LED_Set(GREEN_LED, ON); // 这里跑LwIP的定时检查 ethernetif_input(&gnetif); } else { LED_Toggle(RED_LED); HAL_Delay(500); } } }

调试时最实用的技巧:用示波器抓MDIO波形。曾经遇到读取PHYID始终为0xFFFF的问题,最后发现是MAC的MDC时钟分频系数不对。STM32的ETHMACMIIAR寄存器中,CR位需要根据系统时钟频率配置,72MHz主频时建议设为0x1C(即28分频)。

完整工程里还有个关键点——中断优先级配置。接收中断要设为最高优先级,不然在高流量时容易丢包。这里给出NVIC配置参考:

HAL_NVIC_SetPriority(ETH_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ETH_IRQn);

最后提醒各位,DP83848的硬件复位信号至少要保持10ms低电平。曾经有兄弟偷懒用RC电路做复位,结果每次上电初始化都失败,改成MCU控制复位脚后才正常。

http://www.jsqmd.com/news/593774/

相关文章:

  • 02_Elasticsearch知识体系之Mapping映射设计与索引建模实战
  • 深入解析build.prop:从基础参数到高级定制指南
  • YOLOv11涨点改进| AAAI 2025 |自研创新首发、特征融合改进篇| 使用TAMoE任务自适应混合专家模块,多专家协同合作,各司其职,助力各种任务的目标检测,图像分割,多模态融合目标检测涨点
  • 05_Elasticsearch知识体系之BM25向量搜索与混合检索实战
  • 2026届必备的五大降AI率神器实际效果
  • 突破企业AI应用开发瓶颈:Awesome-Dify-Workflow无代码解决方案深度剖析
  • 04_Elasticsearch知识体系之ESQL管道查询与JOIN分析实战
  • 一台机器也能玩转StarRocks?手把手教你搭建单机测试环境(附避坑指南)
  • 2025届最火的降重复率网站推荐榜单
  • 06_Elasticsearch知识体系之IngestPipelines数据处理与增强实战
  • 如何从零搭建Cubli_Mini:开源自平衡机器人完整制作指南
  • 内部链接 - -王心雨
  • SMU Debug Tool完全指南:AMD Ryzen硬件调试的终极解决方案
  • 别只盯着TCP!拆解大疆源码里MQTT协议的双通道设计:BASIC与DRC到底有啥区别?
  • AI教程——让每个人都能高效写出好故事
  • 2025届最火的AI学术方案实际效果
  • 别再踩坑了!评测5款开源IM源码后,我为什么最终选了鸽哒(附原生/H5性能对比)
  • 计算机毕业设计:Python地铁多维度运营分析与数据管理系统 Django框架 数据分析 可视化 大数据 机器学习 深度学习(建议收藏)✅
  • Grok 4.1 API 完全指南:性能实测、成本测算与接入方案(2026)
  • Android WMS实战:从Toast到悬浮窗,手把手教你理解窗口的‘一生’
  • 从选题到发布全托管:我用OpenClaw搭建了个人自媒体AI流水线
  • 利用ApexSQLLog实现SQLServer日志精准恢复:从误操作到数据还原
  • 综合能源系统中的经济-碳协调:最优调度和灵敏度分析【IEEE33节点】附Matlab代码
  • Windows脚本 | 利用scrcpy实现音画分离投屏的进阶玩法
  • AI for Science 之数论:当人工智能叩响数学王冠的大门
  • 《Foundation 网格 - 大型设备》
  • STM32入门——几个简单的代码(22)
  • 网站主机技术概述
  • 2026届最火的AI论文助手推荐榜单
  • 云原生下的PostgreSQL高可用实战:在K8s里用StatefulSet和Patroni API告别VIP和HAProxy