#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); }