motor_f407/User/system/bsp/spis.c

812 lines
26 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "spis.h"
#include "delay.h"
#define SPI_TIMEOUT 2000
#define CMD_RDSR 0x05 /*!< Read Status Register instruction */
#define CMD_WRSR 0x01 /*!< Write Status Register instruction */
#define CMD_WREN 0x06 /*!< Write enable instruction */
#define CMD_WRDI 0x04 /*!< Write disable instruction */
#define CMD_READ 0x03 /*!< Read from Memory instruction */
#define CMD_WRITE 0x02 /*!< Write to Memory instruction */
#define DUMMY_BYTE 0xA5 ///< 虚拟字节
static inline void spi_delay(spi_t *handle); // 延时函数
static inline void spi_rdy_high(spi_t *handle); // RDY高电平
static inline void spi_rdy_low(spi_t *handle); // RDY低电平
static inline void spi_cs_high(spi_t *handle); // CS高电平
static inline void spi_cs_low(spi_t *handle); // CS低电平
static inline void spi_mosi_high(spi_t *handle); // MOSI高电平
static inline void spi_mosi_low(spi_t *handle); // MOSI低电平
static inline void spi_sck_high(spi_t *handle); // SCK高电平
static inline void spi_sck_low(spi_t *handle); // SCK低电平
static inline uint8_t spi_miso_read(spi_t *handle); // 读取MISO电平
static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data); // 读写一个字节
static void spi_reset(spi_t *handle); // 复位
static BOOL spi_write(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); // 写数据
static BOOL spi_read(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); // 读数据
static void spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写寄存器
static uint8_t spi_read_reg(spi_t *handle, uint8_t reg); // 读寄存器
static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi); // 硬件SPI
static 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
static void _spi_dma_callback(spi_t *handle); // DMA发送完成回调
static BOOL _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length); // DMA发送数据
static uint8_t _read_drdy(spi_t *handle); // 读取DRDY电平
static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 写多个寄存器
static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 读多个寄存器
static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写单个寄存器
static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg); // 读单个寄存器
static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd); // 写命令
static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len); // 写数据
/**
* @brief 创建一个SPI总线设备
* @param {spi_type_e} spi_type SPI总线的类型
* @param {spi_gpio_group_t} gpios SPI总线的GPIO配置
* @param {uint16_t} delay_ticks SPI总线的延时参数
* @return {*} 创建的SPI总线设备句柄
* @note: 该函数用于创建一个SPI总线设备。它首先断言spi_type在有效的范围内然后创建一个spi_t结构体并将gpios和delay_ticks的内存地址复制到handle结构体中。接着根据spi_type的值设置不同的接口函数。最后返回handle结构体。
*/
spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks)
{
DBG_ASSERT(spi_type < SPI_TYPE_MAX __DBG_LINE);
spi_t *handle = (spi_t *)osel_mem_alloc(sizeof(spi_t));
osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(spi_gpio_group_t));
handle->delay_ticks = delay_ticks;
handle->spi_type = spi_type;
handle->simualte_gpio = TRUE;
handle->interface.hardware_enable = _hardware_enable;
handle->interface.dma_enable = _dma_enable;
handle->interface.spi_dma_send = _spi_dma_send;
handle->interface.spi_dma_callback = _spi_dma_callback;
if (spi_type == SPI_TYPE_NORMAL)
{
handle->interface.u.normal.write_reg = _spi_write_reg;
handle->interface.u.normal.read_reg = _spi_read_reg;
handle->interface.u.normal.write_regs = _write_regs;
handle->interface.u.normal.read_regs = _read_regs;
handle->interface.u.normal.read_drdy = _read_drdy;
handle->interface.u.normal.spi_send = spi_read_write_byte;
handle->interface.u.normal.spi_reset = spi_reset;
handle->interface.u.normal.spi_read = spi_read;
handle->interface.u.normal.spi_write = spi_write;
handle->interface.u.normal.spi_write_reg = spi_write_reg;
handle->interface.u.normal.spi_read_reg = spi_read_reg;
handle->cfg.cmd_rdsr = CMD_RDSR;
handle->cfg.cmd_wrsr = CMD_WRSR;
handle->cfg.cmd_wren = CMD_WREN;
handle->cfg.cmd_wrdi = CMD_WRDI;
handle->cfg.cmd_read = CMD_READ;
handle->cfg.cmd_write = CMD_WRITE;
handle->cfg.dummy_byte = DUMMY_BYTE;
handle->cfg.continuous_write = FALSE;
}
else if (spi_type == SPI_TYPE_LCD)
{
handle->interface.u.lcd.write_cmd = _spi_write_cmd;
handle->interface.u.lcd.write_data = _spi_write_data;
}
else
{
DBG_ASSERT(FALSE __DBG_LINE);
}
return handle;
}
void spi_free(spi_t *handle)
{
if (handle != NULL)
{
gpio_free(handle->gpios.cs);
gpio_free(handle->gpios.rdy);
gpio_free(handle->gpios.rst);
gpio_free(handle->gpios.mosi);
gpio_free(handle->gpios.miso);
gpio_free(handle->gpios.sck);
osel_mem_free(handle);
}
}
/**
* @brief 硬件SPI模式
* @param {spi_t} *handle SPI总线设备句柄
* @param {SPI_TypeDef} *spi SPI总线的寄存器结构体指针
* @return {*} 无
* @note: 该函数用于设置SPI总线的硬件模式。它首先断言handle不为空然后断言spix不为空。接着将handle的simulate_gpio设置为FALSE并将spix的地址赋值给handle->spix。最后调用SPI_ENABLE函数启用SPI总线。
*/
static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(spi != NULL __DBG_LINE);
handle->simualte_gpio = FALSE;
handle->spi = spi;
SPI_ENABLE(spi);
}
static 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)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(dma != NULL __DBG_LINE);
DBG_ASSERT(handle->spi != NULL __DBG_LINE);
handle->dma = dma;
handle->dma_rx_channel = dma_rx_channel;
handle->dma_tx_channel = dma_tx_channel;
handle->rx_dma_ok = TRUE;
handle->tx_dma_ok = TRUE;
if (dma_rx_cb != NULL)
{
handle->dma_rx_cb = dma_rx_cb;
}
if (dma_tx_cb != NULL)
{
handle->dma_tx_cb = dma_tx_cb;
}
LL_DMA_SetPeriphAddress(dma, dma_tx_channel, LL_SPI_DMA_GetRegAddr(handle->spi));
LL_DMA_ClearFlag_GI1(dma);
LL_DMA_ClearFlag_TC1(dma);
LL_DMA_EnableIT_TC(dma, dma_tx_channel);
LL_SPI_EnableDMAReq_TX(handle->spi);
LL_SPI_Enable(handle->spi);
}
static void _spi_dma_callback(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->dma_tx_cb != NULL)
{
handle->dma_tx_cb(handle);
}
if (handle->dma_rx_cb != NULL)
{
handle->dma_rx_cb(handle);
}
}
static BOOL _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length)
{
handle->tx_dma_ok = FALSE;
LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
LL_DMA_SetMemoryAddress(handle->dma, handle->dma_tx_channel, (uint32_t)data);
LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, length);
LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
uint16_t i = 0;
while (handle->tx_dma_ok == FALSE)
{
i++;
if (i > 50000)
{
__NOP();
break;
}
}
return handle->tx_dma_ok == TRUE ? TRUE : FALSE;
}
/**
* @brief 读取数据准备好信号
* @param {spi_t} *handle SPI总线设备句柄
* @return {uint8_t} 数据准备好信号的值
* @note: 该函数用于读取SPI总线的数据准备好信号。它首先断言handle不为空然后返回handle的gpios.rdy的读取结果。
*/
static uint8_t _read_drdy(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
return handle->gpios.rdy->read(*handle->gpios.rdy);
}
/**
* @brief 写入单个寄存器
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg 寄存器号
* @param {uint8_t} data 寄存器值
* @return {*} 操作结果
* @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空然后断言data不为空。接着将SPI总线的CS引脚设置为低电平发送寄存器号和寄存器值最后将SPI总线的CS引脚设置为高电平返回操作结果。
*/
static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(len != 0 __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg); // 发送寄存器号
while (len--)
{
spi_read_write_byte(handle, *data); // 写入寄存器的值
data++;
}
spi_cs_high(handle);
return status;
}
/**
* @brief 读取多个寄存器
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg 寄存器号
* @param {uint8_t} *data 寄存器值的指针
* @param {uint8_t} len 寄存器值的个数
* @return {uint8_t} 操作结果
* @note: 该函数用于读取SPI总线的多个寄存器。它首先断言handle不为空然后断言data不为空接着断言len大于0。接着将SPI总线的CS引脚设置为低电平发送寄存器号然后循环读取多个寄存器的值最后将SPI总线的CS引脚设置为高电平返回操作结果。
*/
static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(len != 0 __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg);
for (uint8_t i = 0; i < len; i++)
{
data[i] = spi_read_write_byte(handle, 0xff); // 读出数据
}
spi_cs_high(handle);
return status;
}
/**
* @brief 写入单个寄存器
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg 寄存器号
* @param {uint8_t} data 寄存器值
* @return {*} 操作结果
* @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空然后将SPI总线的CS引脚设置为低电平发送寄存器号和寄存器值最后将SPI总线的CS引脚设置为高电平返回操作结果。
*/
static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg); // 发送寄存器号
spi_read_write_byte(handle, data); // 写入寄存器的值
spi_cs_high(handle);
return status;
}
/**
* @brief 读取单个寄存器
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg 寄存器号
* @return {*} 寄存器值
* @note: 该函数用于读取SPI总线的单个寄存器。它首先断言handle不为空然后将SPI总线的CS引脚设置为低电平发送寄存器号接着读取寄存器的值最后将SPI总线的CS引脚设置为高电平返回寄存器值。
*/
static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg)
{
uint8_t reg_val = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_cs_low(handle);
spi_read_write_byte(handle, reg); // 发送寄存器号
reg_val = spi_read_write_byte(handle, 0);
spi_cs_high(handle);
return reg_val;
}
/**
* @brief 写入命令
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} cmd 命令
* @return {*} 操作结果
* @note: 该函数用于写入SPI总线的命令。它首先断言handle不为空然后将SPI总线的RDY引脚设置为低电平发送命令最后将SPI总线的CS引脚设置为高电平返回操作结果。
*/
static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_rdy_low(handle);
spi_cs_low(handle);
status = spi_read_write_byte(handle, cmd); // 发送命令
spi_cs_high(handle);
return status;
}
/**
* @brief 写入数据
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} *data 要写入的数据的指针
* @param {uint16_t} len 要写入的数据的长度
* @return {*} 操作结果
* @note: 该函数用于写入SPI总线的数据。它首先断言handle不为空然后将SPI总线的RDY引脚设置为高电平发送数据最后将SPI总线的CS引脚设置为高电平返回操作结果。
*/
static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_rdy_high(handle);
spi_cs_low(handle);
for (uint16_t i = 0; i < len; i++)
{
status = spi_read_write_byte(handle, *data);
data++;
}
spi_cs_high(handle);
return status;
}
/**
* @brief SPI延时函数
* @param {spi_t} *handle SPI总线设备句柄
* @return {*} 无
* @note: 该函数用于SPI总线的延时。它首先断言handle不为空然后根据handle的delay_ticks的值循环执行NOP指令。
*/
static inline void spi_delay(spi_t *handle)
{
uint16_t count = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
count = handle->delay_ticks;
if (count > 0)
{
while (count--)
{
__NOP();
}
}
}
static BOOL spi_wait_flag(spi_t *handle, uint32_t flag, uint32_t timeout)
{
uint32_t i = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (flag == LL_SPI_SR_TXE)
{
while (LL_SPI_IsActiveFlag_TXE(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
{
__NOP();
}
}
}
else if (flag == LL_SPI_SR_RXNE)
{
while (LL_SPI_IsActiveFlag_RXNE(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
{
__NOP();
}
}
}
else if (flag == LL_SPI_SR_BSY)
{
while (LL_SPI_IsActiveFlag_BSY(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
{
__NOP();
}
}
}
else
{
DBG_ASSERT(FALSE __DBG_LINE);
}
return TRUE; // 成功
}
/**
* @brief 读写一个字节
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} tx_data 要写入的数据
* @return {*} 读取到的数据
* @note: 该函数用于SPI总线的读写一个字节。它首先断言handle不为空然后根据handle的simulate_gpio的值选择模拟SPI或硬件SPI。最后返回读取到的数据。
*/
static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data)
{
uint8_t bit_ctr;
uint8_t rdata = 0xff;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->simualte_gpio == TRUE)
{
// 模拟SPI
for (bit_ctr = 0; bit_ctr < 8; bit_ctr++)
{
spi_sck_low(handle);
spi_delay(handle);
if (tx_data & 0x80)
spi_mosi_high(handle);
else
spi_mosi_low(handle);
spi_delay(handle);
spi_sck_high(handle);
spi_delay(handle);
tx_data = (tx_data << 1);
rdata = rdata << 1;
if (NULL != handle->gpios.miso->port)
{
if (spi_miso_read(handle) == 1)
rdata += 0x01;
}
}
return (rdata);
}
else
{
LL_SPI_TransmitData8(handle->spi, tx_data);
if (spi_wait_flag(handle, LL_SPI_SR_RXNE, SPI_TIMEOUT) == FALSE)
{
return 0xff;
}
rdata = LL_SPI_ReceiveData8(handle->spi);
return rdata;
}
}
static void _write_enable(spi_t *handle)
{
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_wren);
handle->gpios.cs->set(*handle->gpios.cs);
}
static void _write_disable(spi_t *handle)
{
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_wrdi);
handle->gpios.cs->set(*handle->gpios.cs);
}
static uint8_t _read_status(spi_t *handle)
{
uint8_t data;
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_rdsr);
data = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte);
handle->gpios.cs->set(*handle->gpios.cs);
return data;
}
static void _ready(spi_t *handle)
{
uint16_t count = 0;
while (_read_status(handle) & 0x01)
{
if (count++ > 20000)
{
break;
}
else
{
__NOP();
}
}
}
static BOOL spi_write(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length)
{
BOOL ret = TRUE;
uint8_t cnt = 0; // 返回值检查
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(length > 0 __DBG_LINE);
DBG_ASSERT(handle->cfg.page_size > 0 __DBG_LINE);
uint32_t page_size = handle->cfg.page_size;
_write_enable(handle); // 写入使能命令
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_write); // 发送写入命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr);
if (cnt == 0)
{
return FALSE;
}
}
while (length--)
{
cnt = handle->interface.u.normal.spi_send(handle, *data); // 发送一个字节数据
if (cnt == 0)
{
return FALSE;
}
data++;
if (handle->cfg.continuous_write == FALSE)
{
write_addr++;
if (((write_addr % page_size) == 0) && (length > 0))
{
// 一页写完
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
_ready(handle);
_write_enable(handle); // 写入使能命令
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_write); // 发送写入命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr);
if (cnt == 0)
{
return FALSE;
}
}
}
}
}
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
_ready(handle);
_write_disable(handle);
return ret;
}
static void spi_write_reg(spi_t *handle, uint8_t reg, uint8_t value)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
_write_enable(handle); // 写入使能命令
handle->interface.u.normal.write_reg(handle, reg, value);
_ready(handle);
_write_disable(handle); // 写入禁止命令
}
static uint8_t spi_read_reg(spi_t *handle, uint8_t reg)
{
uint8_t data;
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, reg);
data = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte);
handle->gpios.cs->set(*handle->gpios.cs);
return data;
}
static BOOL spi_read(spi_t *handle, uint32_t read_addr, uint8_t *data, uint16_t length)
{
BOOL ret = TRUE;
uint8_t cnt = 0; // 返回值检查
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(length > 0 __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_read); // 发送读取命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr);
if (cnt == 0)
{
return FALSE;
}
}
for (uint16_t i = 0; i < length; i++) // 循环读取数据
{
data[i] = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte); // 发送空字节,读取实际数据
}
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
return ret;
}
static void spi_reset(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs);
delay_tick(10);
handle->gpios.cs->set(*handle->gpios.cs);
delay_tick(10);
}
/**
* @brief 用于将SPI串行外围接口设备的复位RST引脚设置为高
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_rdy_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.rdy->set(*handle->gpios.rdy);
}
/**
* @brief 用于将SPI串行外围接口设备的复位RST引脚设置为低
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_rdy_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.rdy->reset(*handle->gpios.rdy);
}
/**
* @brief 用于将SPI串行外围接口设备的芯片选择CS引脚设置为高
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->set(*handle->gpios.cs);
spi_delay(handle);
}
/**
* @brief 用于将SPI串行外围接口设备的芯片选择CS引脚设置为低
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs);
spi_delay(handle);
}
/**
* @brief 用于将SPI串行外围接口设备的时钟SCK引脚设置为高
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.mosi->set(*handle->gpios.mosi);
}
/**
* @brief 用于将SPI串行外围接口设备的输出MOSI引脚设置为低
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.mosi->reset(*handle->gpios.mosi);
}
/**
* @brief 用于将SPI串行外围接口设备的时钟SCK引脚设置为高
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.sck->set(*handle->gpios.sck);
}
/**
* @brief 用于将SPI串行外围接口设备的时钟SCK引脚设置为低
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.sck->reset(*handle->gpios.sck);
}
/**
* @brief 用于读取SPI串行外围接口设备的输入MISO引脚的电平
* @param {spi_id_e} id
* @return {*}
*/
static inline uint8_t spi_miso_read(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
return handle->gpios.miso->read(*handle->gpios.miso);
}