当前位置:网站首页>i.MX - RT1052 SPI和 I2C接口

i.MX - RT1052 SPI和 I2C接口

2022-06-21 11:58:00 夏沫の浅雨

写在前面:

本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。



SPI和 I2C协议的分析可以看之前的篇章:UART/USRAT、I2C、SPI通信方式扫盲


一、SPI

1.1 信号线

在这里插入图片描述


1.2 架构框图

在这里插入图片描述


1.3 传输

  • 在以下情况下,LPSPI启动SPI总线传输:
    • 数据写入发送 FIFO
    • 并置位(或禁用)了HREQ引脚
    • 使能了 LPSPI
  • 要执行 SPI总线传输,LPSPI使用以下命令中配置的属性: 发送命令寄存器(TCR),并使用时钟配置寄存器(CCR)中的时序参数。
  • SPI总线在到达 FRAMESZ配置后传输结束,或者当新的发送命令字位于发送/命令FIFO的顶部时,SPI总线传输结束于字的末尾。
  • 仅在下次 LPSPI空闲时(LPSPI完成当前传输并且发送命令寄存器(TCR)为空)时才检查HREQ输入。

 循环 FIFO:发送/命令 FIFO还支持循环 FIFO功能,该功能使 LPSPI主设备能够(周期性地)重复一次短的数据传输,该传输可以适合发送/命令 FIFO,而无需其他 FIFO访问。 启用循环 FIFO后,将保存 FIFO读取指针的当前状态,并且状态标志不会更新。 在发送/命令 FIFO被认为是空的并且 LPSPI处于空闲状态之后,FIFO读取指针将用保存的版本恢复,因此在启用循环 FIFO模式时,发送/命令 FIFO的内容不会被永久从 FIFO中拉出。


1.4 时钟环回

1、可以将 LPSPI主器件配置为使用 2个时钟中的 1个来采样输入数据(例如LPSPI_SIN):

  • 直接使用 LPSPI_SCK输出时钟
  • 或 LPSPI_SCK输出时钟的延迟版本

2、LPSPI_SCK的延迟版本被 LPSPI_SCK引脚输出延迟加上 LPSPI_SCK引脚输入延迟所延迟,并通过设置CFGR1 [SAMPLE]进行配置。
3、启用 LPSPI_SCK的环回版本可以缩短从机输入数据的建立时间。

在这里插入图片描述


1.5 Transactional APIs代码

spi总线一般使用 Transactional APIs来操作;具体可以看官方 SDK包里下面路径的例程:
   …\ boards\ evkbimxrt1050\ demo_apps\ lpspi_loopback

/*! * @name Transactional * @{ */
/*Transactional APIs*/

/*! * @brief Initializes the LPSPI master handle. * * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a * specified LPSPI instance, call this API once to get the initialized handle. * @param base LPSPI peripheral address. * @param handle LPSPI handle pointer to lpspi_master_handle_t. * @param callback DSPI callback. * @param userData callback function parameter. */
void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base,
                                      lpspi_master_handle_t *handle,
                                      lpspi_master_transfer_callback_t callback,
                                      void *userData);

/*! * @brief LPSPI master transfer data using a polling method. * * This function transfers data using a polling method. This is a blocking function, which does not return until all * transfers have been * completed. * * Note: * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. * For bytesPerFrame greater than 4: * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. * * @param base LPSPI peripheral address. * @param transfer pointer to lpspi_transfer_t structure. * @return status of status_t. */
status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer);

/*! * @brief LPSPI master transfer data using an interrupt method. * * This function transfers data using an interrupt method. This is a non-blocking function, which returns right away. * When all data * is transferred, the callback function is called. * * Note: * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. * For bytesPerFrame greater than 4: * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. * @param transfer pointer to lpspi_transfer_t structure. * @return status of status_t. */
status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer);

/*! * @brief Gets the master transfer remaining bytes. * * This function gets the master transfer remaining bytes. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. * @param count Number of bytes transferred so far by the non-blocking transaction. * @return status of status_t. */
status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count);

/*! * @brief LPSPI master abort transfer which uses an interrupt method. * * This function aborts a transfer which uses an interrupt method. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. */
void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle);

/*! * @brief LPSPI Master IRQ handler function. * * This function processes the LPSPI transmit and receive IRQ. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. */
void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle);

/*! * @brief Initializes the LPSPI slave handle. * * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a * specified LPSPI instance, call this API once to get the initialized handle. * * @param base LPSPI peripheral address. * @param handle LPSPI handle pointer to lpspi_slave_handle_t. * @param callback DSPI callback. * @param userData callback function parameter. */
void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base,
                                     lpspi_slave_handle_t *handle,
                                     lpspi_slave_transfer_callback_t callback,
                                     void *userData);

/*! * @brief LPSPI slave transfer data using an interrupt method. * * This function transfer data using an interrupt method. This is a non-blocking function, which returns right away. * When all data * is transferred, the callback function is called. * * Note: * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. * For bytesPerFrame greater than 4: * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4. * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. * @param transfer pointer to lpspi_transfer_t structure. * @return status of status_t. */
status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer);

/*! * @brief Gets the slave transfer remaining bytes. * * This function gets the slave transfer remaining bytes. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. * @param count Number of bytes transferred so far by the non-blocking transaction. * @return status of status_t. */
status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count);

/*! * @brief LPSPI slave aborts a transfer which uses an interrupt method. * * This function aborts a transfer which uses an interrupt method. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. */
void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle);

/*! * @brief LPSPI Slave IRQ handler function. * * This function processes the LPSPI transmit and receives an IRQ. * * @param base LPSPI peripheral address. * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. */
void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle);

二、I2C

2.1 信号线

在这里插入图片描述

2.2 架构框图

在这里插入图片描述

2.3 数据收发

  • 发送和接收数据寄存器是双缓冲的,仅分别在从发送和从接收传输期间更新。
  • 可以将接收到的从机地址配置为从接收数据寄存器(例如,使用DMA传输数据时)或从地址状态寄存器中读取。
  • 可以将发送数据寄存器配置为仅在检测到从发送传输之后请求数据,或者在发送数据寄存器为空时请求新数据。
  • 仅当设置了发送数据标志时,才应写入发送数据寄存器。
  • 仅当设置了接收数据标志(或设置了地址有效标志且 RXCFG = 1)时,才应读取接收数据寄存器。
  • 仅当设置了地址有效标志时,才应读取地址状态寄存器。

2.4 Transactional APIs代码

spi总线一般使用 Transactional APIs来操作;具体可以看官方 SDK包里下面路径的例程:
   …\ boards\ evkbimxrt1050\ driver_examples\ lpi2c\ interrupt_b2b_transfer\ master(or slave) Master:

/*! @name Non-blocking */
/*@{*/

/*! * @brief Creates a new handle for the LPI2C master non-blocking APIs. * * The creation of a handle is for use with the non-blocking APIs. Once a handle * is created, there is not a corresponding destroy handle. If the user wants to * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called. * * * @note The function also enables the NVIC IRQ for the input LPI2C. Need to notice * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to * enable the associated INTMUX IRQ in application. * * @param base The LPI2C peripheral base address. * @param[out] handle Pointer to the LPI2C master driver handle. * @param callback User provided pointer to the asynchronous callback function. * @param userData User provided pointer to the application callback data. */
void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
                                      lpi2c_master_handle_t *handle,
                                      lpi2c_master_transfer_callback_t callback,
                                      void *userData);

/*! * @brief Performs a non-blocking transaction on the I2C bus. * * @param base The LPI2C peripheral base address. * @param handle Pointer to the LPI2C master driver handle. * @param transfer The pointer to the transfer descriptor. * @retval kStatus_Success The transaction was started successfully. * @retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking * transaction is already in progress. */
status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
                                         lpi2c_master_handle_t *handle,
                                         lpi2c_master_transfer_t *transfer);

/*! * @brief Returns number of bytes transferred so far. * @param base The LPI2C peripheral base address. * @param handle Pointer to the LPI2C master driver handle. * @param[out] count Number of bytes transferred so far by the non-blocking transaction. * @retval kStatus_Success * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress. */
status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count);

/*! * @brief Terminates a non-blocking LPI2C master transmission early. * * @note It is not safe to call this function from an IRQ handler that has a higher priority than the * LPI2C peripheral's IRQ priority. * * @param base The LPI2C peripheral base address. * @param handle Pointer to the LPI2C master driver handle. * @retval kStatus_Success A transaction was successfully aborted. * @retval #kStatus_LPI2C_Idle There is not a non-blocking transaction currently in progress. */
void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle);

/*@}*/

/*! @name IRQ handler */
/*@{*/

/*! * @brief Reusable routine to handle master interrupts. * @note This function does not need to be called unless you are reimplementing the * nonblocking API's interrupt handler routines to add special functionality. * @param base The LPI2C peripheral base address. * @param handle Pointer to the LPI2C master driver handle. */
void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, lpi2c_master_handle_t *handle);

/*@}*/

Slave:

/*! @name Slave non-blocking */
/*@{*/

/*! * @brief Creates a new handle for the LPI2C slave non-blocking APIs. * * The creation of a handle is for use with the non-blocking APIs. Once a handle * is created, there is not a corresponding destroy handle. If the user wants to * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called. * * @note The function also enables the NVIC IRQ for the input LPI2C. Need to notice * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to * enable the associated INTMUX IRQ in application. * @param base The LPI2C peripheral base address. * @param[out] handle Pointer to the LPI2C slave driver handle. * @param callback User provided pointer to the asynchronous callback function. * @param userData User provided pointer to the application callback data. */
void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
                                     lpi2c_slave_handle_t *handle,
                                     lpi2c_slave_transfer_callback_t callback,
                                     void *userData);

/*! * @brief Starts accepting slave transfers. * * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked * from the interrupt context. * * The set of events received by the callback is customizable. To do so, set the @a eventMask parameter to * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive. * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as * a convenient way to enable all events. * * @param base The LPI2C peripheral base address. * @param handle Pointer to lpi2c_slave_handle_t structure which stores the transfer state. * @param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify * which events to send to the callback. Other accepted values are 0 to get a default set of * only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events. * * @retval kStatus_Success Slave transfers were successfully started. * @retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle. */
status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask);

/*! * @brief Gets the slave transfer status during a non-blocking transfer. * @param base The LPI2C peripheral base address. * @param handle Pointer to i2c_slave_handle_t structure. * @param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not * required. * @retval kStatus_Success * @retval kStatus_NoTransferInProgress */
status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count);

/*! * @brief Aborts the slave non-blocking transfers. * @note This API could be called at any time to stop slave for handling the bus events. * @param base The LPI2C peripheral base address. * @param handle Pointer to lpi2c_slave_handle_t structure which stores the transfer state. * @retval kStatus_Success * @retval #kStatus_LPI2C_Idle */
void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle);

/*@}*/

/*! @name Slave IRQ handler */
/*@{*/

/*! * @brief Reusable routine to handle slave interrupts. * @note This function does not need to be called unless you are reimplementing the * non blocking API's interrupt handler routines to add special functionality. * @param base The LPI2C peripheral base address. * @param handle Pointer to lpi2c_slave_handle_t structure which stores the transfer state. */
void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle);

/*@}*/

原网站

版权声明
本文为[夏沫の浅雨]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_42992084/article/details/108420289