/*** * @Author: xxx * @Date: 2023-08-01 15:15:53 * @LastEditors: xxx * @LastEditTime: 2023-08-10 10:37:54 * @Description: SPI驱动, 用于SPI设备的读写操作 * @email: * @Copyright (c) 2023 by xxx, All Rights Reserved. */ /** 使用教程: 1. 初始化 spi_t *_spi = NULL; spi_gpio_group_t gpios; gpios.cs = gpio_create(EEPROM_M95_CS_PORT, EEPROM_M95_CS_PIN); gpios.mosi = gpio_create(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin); gpios.sck = gpio_create(SPI_CLK_GPIO_Port, SPI_CLK_Pin); gpios.miso = gpio_create(SPI_MISO_GPIO_Port, SPI_MISO_Pin); gpios.rst = gpio_create(NULL, 0); gpios.rdy = gpio_create(NULL, 0); _spi = spi_create(SPI_TYPE_NORMAL, gpios, 0); 2. 使用 _spi->gpios.cs->reset(*_spi->gpios.cs); _spi->interface.u.normal.spi_send(_spi, M95_CMD_READ); _spi->interface.u.normal.spi_send(_spi, read_addr >> 8); _spi->interface.u.normal.spi_send(_spi, read_addr & 0xff); for (uint16_t i = 0; i < length; i++) { data[i] = _spi->interface.u.normal.spi_send(_spi, M95_DUMMY_BYTE); } _spi->gpios.cs->set(*_spi->gpios.cs); 3. 使用LCD spi_t *_spi = NULL; spi_gpio_group_t gpios; gpios.cs = gpio_create(LCD_CS_GPIO_Port, LCD_CS_Pin); gpios.mosi = gpio_create(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin); gpios.sck = gpio_create(SPI_CLK_GPIO_Port, SPI_CLK_Pin); gpios.rst = gpio_create(LCD_RST_GPIO_Port, LCD_RST_Pin); gpios.rdy = gpio_create(LCD_RS_GPIO_Port, LCD_RS_Pin); gpios.miso = gpio_create(NULL, 0); _spi = spi_create(SPI_TYPE_LCD, gpios, 0); _spi->interface.hardware_enable(_spi); // LCD模拟IO比较慢 _spi->spi = SPI1; lcd = lcd_create(_spi); lcd->driver.init(lcd); */ #ifndef __SPIS_H__ #define __SPIS_H__ #include "lib.h" #include "gpios.h" #define SPI_ENABLE(SPIX) LL_SPI_Enable(SPIX) typedef struct SPIS spi_t; typedef void spis_dma_callback(spi_t *handle); typedef enum { SPI_TYPE_NORMAL = 0, // SPI1:NORMAL SPI_TYPE_LCD, // SPI2:LCD SPI_TYPE_MAX, } spi_type_e; typedef struct { // NORMAL:通过SPI写单个寄存器 uint8_t (*write_reg)(spi_t *handle, uint8_t reg, uint8_t data); // NORMAL:通过SPI读取单个寄存器值 uint8_t (*read_reg)(spi_t *handle, uint8_t reg); uint8_t (*read_drdy)(spi_t *handle); // 获取SPI DRDY引脚的值 uint8_t (*write_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 通过SPI写多个寄存器 uint8_t (*read_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 通过SPI读多个寄存器 uint8_t (*spi_send)(spi_t *handle, uint8_t data); // 通过SPI发送数据 } spi_normal_interface_t; typedef struct { // LCD:通过SPI写命令 uint8_t (*write_cmd)(spi_t *handle, uint8_t cmd); // LCD:通过SPI写数据 uint8_t (*write_data)(spi_t *handle, uint8_t *data, uint16_t len); } spi_lcd_interface_t; typedef struct { union { spi_normal_interface_t normal; spi_lcd_interface_t lcd; } u; void (*hardware_enable)(spi_t *handle, SPI_TypeDef *spi); // 硬件SPI void (*dma_enable)(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb, uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // DMA SPI void (*spi_dma_callback)(spi_t *spi); // DMA发送完成回调 void (*spi_dma_send)(spi_t *handle, uint8_t *data, uint16_t length); // DMA发送 } spi_interface_t; typedef struct { gpio_t *mosi; // MOSI gpio_t *miso; // MISO gpio_t *sck; // SCK gpio_t *cs; // CS gpio_t *rst; // RST gpio_t *rdy; // DRDY } spi_gpio_group_t; struct SPIS { spi_type_e spi_type; // SPI类型 uint16_t delay_ticks; // 延时多少个NOP spi_gpio_group_t gpios; // SPI引脚 spi_interface_t interface; // SPI接口 SPI_TypeDef *spi; // SPI外设 BOOL simualte_gpio; // 是否模拟GPIO // DMA DMA_TypeDef *dma; // 外部设置 uint32_t dma_rx_channel; // 外部设置 uint32_t dma_tx_channel; // 外部设置 __IO BOOL rx_dma_ok; __IO BOOL tx_dma_ok; spis_dma_callback *dma_rx_cb; // DMA接收回调函数 spis_dma_callback *dma_tx_cb; // DMA发送回调函数 }; extern spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks); // 创建SPI extern void spi_free(spi_t *spi); // 释放SPI #endif // __SPIS_H__