| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 -> 正文阅读 |
|
[嵌入式]RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 |
系列文章目录RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 目录 0 概述在上一篇内容中,我适配了STM32的外部SRAM,并将其加载到内存管理中。我目前适配RTT的板子是用于工业物联网远程控制的,因此板载了一个以太网口。我们需要开启RTT的lwip软件包。 由于本文中包含一些RTT源码解析,如果只想按步骤操作的话请按以下顺序查看 1.1 配置ENC28J60接口 0.0 参考资料RT-Thread开发指南 0.1 硬件资源MCU:STM32F103ZET6 0.2 软件资源开发环境:RT-Thread Studio 0.3 RTT的启动与底层驱动初始化流程在上一篇中,由于RTT并没有FSMC类型的设备,所以我们并没有涉及到RTT的驱动框架。在这里我们补充一下RTT的启动流程。 ? 转到定义rtthread_startup()的地方,同样在该文件中,如下:
RTT依次对各级进行初始化,初始化顺序参考RTT手册: ? 我们转到rt_hw_board_init()的定义。该函数在【driver→board.c】中。如下:
其中有我们上次讲到的内存堆初始化,hw_board_init(...)则是板级硬件的初始化。我们转到该函数的定义。在【driver→drv_common.c】中,如下: ?其中终于涉及到了HAL库相关初始化的东西,我们继续转到HAL_Init()的定义。该定义在【项目\libraries\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c】中。 ? 我们可以看到在HAL_Init()中前面都是对系统时钟以及中断进行初始化,而在第163行调用了HAL_MspInit()。继续转到HAL_MspInit()的定义。在同文件下面有一个定义,然而这个定义是一个weak类型的,也就是说如果其他地方定义了一个不是weak类型的HAL_MspInit()则执行那个。那么这个文件中的HAL_MspInit()是没意义的,我们在工程中检索一下。发现项目中并没有其他定义,那么RTT是在什么时候初始化相关硬件的呢? 其实,我们只需要打开【项目\driver\drv_spi.c】,可以在里面找到rt_hw_spi_init(...),并且通过INIT_BOARD_EXPORT(rt_hw_spi_init)使其在板级初始化自动运行。也就是在【项目\drvier\board.c】中的rt_hw_board_init()调用的rt_components_board_init()中执行。 ? 1 驱动编写如下图所示,为ENC28J60的电路图以及与STM32的接口。 ? 1.1 配置ENC28J60接口ENC28J60与STM32之间采用SPI接口。在这里我们不直接使用STM32的SPI驱动程序对接ENC28J60的接口,而是使用RTT的接口驱动。 ② 使能SPI总线,并使能RTT自带的ENC28J60 SPI以太网接口 ?我们使能ENC28J60的接口之后,RTT的lwip协议栈也自动被使能。这是因为ENC28J60接口依赖lwip协议栈。 ?保存配置后,在项目工程的【rt-thread】→【components】→【net】目录下可以看到【lwip-2.0.2】的相关文件。 ? lwip的部分我们先不管,首先解决ENC28J60的驱动问题。 ③ 在board.h中启用SPI1 ④ 在stm32f1xx_hal_conf.h中取消#define HAL_SPI_MODULE_ENABLED的注释 ⑤ 在【driver】目录下新建drv_enc28j60.c文件 如下图所示,ENC28J60有6个I/O口,其中REST复位引脚可不管,因为RTT的ENC28J60驱动使用软复位。 ?
首先,我们通过rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_4)配置SPI1总线上的enc28设备使用PG7作为片选引脚CS。 通过INIT_COMPONENT_EXPORT(rt_hw_enc28j60_init)导入到组件级自动初始化。 1.2 RTT设备初始化我们经过第0.3小节的查找得知,RTT是在板级初始化时自动运行spi初始化程序。那么接下来我们需要了解一下RTT究竟初始化了什么,有没有需要我们补充的。
可以看到里面第一个是配置了SPIDMA相关,第二个则是初始spi总线。我们转到rt_hw_spi_bus_init()。整个函数比较长,这里只放一部分。如下:
可以明显的看出这是一个遍历的结构,spi_config[]数组中保存的就是我们的SPI总线列表。也在同文件中定义。可以看到我们只在board.h中启用了SPI1.所以目前列表中只有SPI1. ? 在rt_hw_spi_bus_init()的最后,调用了rt_spi_bus_register(...),并传入了一个结构体stm_spi_ops。该结构体内容如下:
至于内核如何调用结构体我们就不管了,但是我们知道 spi_configure这个函数被传递过去了。我们去看一下spi_configure的内容。
可以看到,里面调用了stm32_spi_init,stm32_spi_init中调用了HAL_SPI_Init(spi_handle)。 这意味着RTT没有初始化SPI1的端口,需要我们补充!!!! 1.3 补充HAL_SPI_MspInit我们打开board.c,在里面添加如下内容:
这里我们只补充了SPI1的相关内容,以后如果需要其他SPI接口,则继续补充。 2 LWIP配置lwip版本我们选择2.0.2,以便获得良好的兼容性。 ?①首先,我们使用了ENC28J60作为网络接口设备,所以我们要打开RTT配置中【网络】【网络接口设备】【使能网络接口设备】。 ?②修改内存占用相关参数 ?③ 是否使能DCHP自动获取IP地址
?静态IP
④ 是否启用ping功能? ? 3 总结完成后编译工程,编译后工程大小为: 我使用的是DHCP自动获取IP,然后通过中断输入ifconfig命令查看网络状态,如下图所示,可以看到已经自动获取到了IP地址。? ?使用ping命令ping www.baidu.com测试网络连接,结果如下所示: ? |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 3:49:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |