This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/system/bsp/spis.h

134 lines
4.5 KiB
C

/***
* @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__