赞
踩
接上次我们使用IO模拟的方式驱动LCD屏幕,由于IO模拟刷屏速度太慢,本次我们使用ESP32的硬件SPI来驱动LCD,在测试过程中遇到了很多坑,所以会详细的讲一下ESP32的SPI外设。
ESP32-S2 系列芯片共有4 个SPI(SPI0,SPI1,SPI2 和SPI3)。SPI0 和SPI1 只可以配置成SPI 存储器模式,
SPI2 既可以配置成SPI 存储器模式又可以配置成通用SPI 模式;SPI3 只可以配置成通用SPI 模式。
• SPI 存储器(SPI Memory) 模式
SPI 存储器模式(SPI0, SPI1 和SPI2)用于连接SPI 接口的外部存储器。SPI 存储器模式下数据传输长度
以字节为单位,最高支持 8 线 STR/DDR 读写操作。时钟频率可配置, STR 模式下支持的最高时钟频率为
80 MHz,DDR 模式下支持的最高时钟频率为40 MHz。
• SPI2 通用SPI (GP-SPI) 模式
SPI2 作为通用 SPI 时,既可以配置成主机模式,又可以配置成从机模式。主机模式支持 2 线全双工和
1/2/4/8 线半双工通信;从机模式支持 2 线全双工和 1/2/4 线半双工通信。通用 SPI 的主机时钟频率可配
置;数据传输长度以字节为单位;时钟极性(CPOL) 和相位(CPHA) 可配置;可连接DMA 通道。
– 在 2 线全双工通信模式下, 主机的时钟最高频率为 80 MHz,从机的时钟最高频率为 40 MHz。支持
SPI 传输的4 种时钟模式。
– 在主机1/2/4/8 线半双工通信模式下,时钟频率最高为80 MHz,支持SPI 传输的4 种时钟模式。
– 在从机1/2/4 线半双工通信模式下,时钟频率最高为40 MHz,也支持SPI 传输的4 种时钟模式。
• SPI3 通用SPI (GP-SPI) 模式
SPI3 只能作为通用SPI,既可以配置成主机模式,又可以配置成从机模式,具有2 线全双工和1 线半双工
通信功能。通用SPI 的主机时钟频率可配置;数据传输长度以字节为单位;时钟极性(CPOL) 和相位(CPHA)
可配置;可连接DMA 通道。
– 在 2 线全双工通信模式下, 主机的时钟频率最高为 80 MHz,从机的时钟频率最高为 40 MHz。支持
SPI 传输的4 种时钟模式。
– 在1 线半双工通信模式下,主机的时钟频率最高为80 MHz,支持SPI 传输的4 种时钟模式;从机的
时钟频率最高为40 MHz,也支持SPI 传输的4 种时钟模式。
在频率这一部分我查阅了很多资料,对于ESP32我看到的大多数描述是如果使用IO_MUX,那么最高频率能到80MHz,如果使用GPIO矩阵,那么最高频率只能到26.6MHz,否则ESP_LOG将会报错;我手上的是ESP32-S2,翻阅了乐鑫官方的数据手册,并没有看到描述必须使用IO_MUX才能将频率配置到80MHz,同时ESP32-S2的IO_MUX列表中我并没有找到SPI3的标注,之有SPI和FSPI。所以对于能不呢配置成80MHz,我们只需要直接配置成80MHz然后打开串口终端,观察是否打印错误信息即可。但是对于实际的频率,并不能确定是80MHz。
我们用SPI主机模式来驱动LCD
ESP32共有4个SPI,与我们熟悉的STM32来说,并不是叫做SPI1,SPI2,SPI3,在ESP32的SPI中,SPI0和SPI1是不提供给用户使用的,在模组中,SPI0/1直接连接外挂的FLASH,当然有一部分ESP32芯片也是带有片上FLASH的,但同样不能将SPI0/1用来驱动其他模块,提供的功能也仅是与外挂的FLASH进行连接。剩余的两个SPI也不叫做SPI2/3,而是叫做FSPI和HSPI,对于这个命名我一开始认为是Fast SPI和High-Speed SPI的缩写,但实际上并不能这样理解,暂且认为它和SPI2/3相同。
通过调用 spi_bus_initialize 初始化 SPI 总线. 确保在 bus_config 结构中设置正确的 IO 引脚. 注意将不需要的信号设置为 -1.
通过调用 spi_bus_add_device 告诉驱动程序连接到总线的 SPI 从设备. 确保在 dev_config 结构中配置设备具有的任何时序要求. 您现在应该拥有该设备的句柄,以便在发送事务时使用.
要与设备交互,请使用您需要的任何事务参数填充一个或多个 spi_transaction_t 结构. 然后以轮询方式或中断方式发送它们:
可选:要对设备执行事务,请在事务之前调用 spi_device_acquire_bus,并在事务之后调用 spi_device_release_bus。
可选:要卸载设备的驱动程序,请以设备句柄作为参数调用 spi_bus_remove_device
可选:要删除总线的驱动程序,请确保没有连接更多驱动程序并调用 spi_bus_free.
下面我们先看看LCD的原理图:
这里的SCL引脚对应SPI的SCLK引脚,SDA引脚对应SPI的MOSI引脚,这里并不需要使用MISO,所以我们将其配置为-1,RES是LCD的复位引脚,在初始化时先要将LCD复位,CS引脚是模块的片选引脚,对于SPI外设,最多可以有三个CS来选择是给所连接的三个外设中的哪一个进行数据传输,CS低电平有效。这里LCD直接连接到了地,所以我们并不需要使用ESP32的硬件SPI的CS来控制。DC是写寄存器/写数据的选择引脚,这里我们直接用软件控制的方式,BLK是LCD的背光选择引脚,记得打开背光,LCD才能正常显示。
下面我们直接来进行配置:
首先我么使用宏来定义使用的管脚:
/* LCD-SPI Pins */
#define LCD_SCLK_PIN 3
#define LCD_MOSI_PIN 4
#define LCD_MISO_PIN -1
#define LCD_CS_PIN -1
#define LCD_HOST FSPI_HOST
#define DMA_CHAN SPI_DMA_CH_AUTO
这里的DMA_CHAN 在官方例程中,是直接配置为LCD_HOST,也就是说我们的LCD_HOST是配置的FSPI_HOST的宏,FSPI_HOST是2,那么DMA通道也就配置成了2;
但是对于ESP32-S2略有不同;我们先看看SDK中的预编译内容:
/**
* @brief SPI DMA channels
*/
typedef enum {
SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
#if CONFIG_IDF_TARGET_ESP32
SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
#endif
SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
} spi_common_dma_t;
这里对DMA通道进行了枚举,我们使用的是ESP32-S2所以将DMA通道配置为SPI_DMA_CH_AUTO
对于最大传输的Size我们直接配置为默认的最大4094即可;
记得首先要创建SPI句柄:
static spi_device_handle_t spi; //创建spi
spi_bus_config_t buscfg = {
.miso_io_num
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。