SPI
简要说明
SPI(Serial Peripheral Interface)是一种高速的、全双工、同步的通信总线。SPI以主从方式工作,通常有一个主设备和一个或多个从设备。
SPI 控制器的信号线描述如下:
- MISO:主设备数据输入,从设备数据输出;
- MOSI:主设备数据输出,从设备数据输入;
- SCLK: 时钟信号,由主设备产生;
- SS:从设备使能信号,由主设备控制。这个信号可以是SPI外设的一部分,也可用GPIO引脚实现。
SPI 典型接线方式如下:
SPI总线支持的四种工作方式,取决于串行同步时钟极性(CPOL)和串行同步时钟相位CPHA的组合。
四种工作方式时序描述如下:
CPOL是用来决定SCLK时钟信号空闲时的电平,CPOL=0,空闲电平为低电平,CPOL=1时,空闲电平为高电平。CPHA是用来决定采样时刻的,CPHA=0,在每个周期的第一个时钟沿采样,第二个时钟沿数据输出;CPHA=1,在每个周期的第二个时钟沿采样,第一个时钟沿数据输出。SPI主模块和与之通信的外设时钟相位和极性应该一致。
接口描述
csi_spi_initialize
spi_handle_t csi_spi_initialize(int32_t idx, spi_event_cb_t cb_event)
功能描述:
- 通过设备号初始化对应的spi实例,返回spi实例的句柄。
参数:
idx
: 设备号。cb_event
: spi实例的事件回调函数(一般在中断上下文执行)。回调函数原型定义见spi_event_cb_t。回调函数类型iic_event_cb_t定义如下:
typedef void (*spi_event_cb_t)(int32_t idx, spi_event_e event);
其中idx为设备号,event 为传给回调函数的事件类型,spi 回调事件枚举类型 spi_event_e
返回值:
- NULL: 初始化失败。
- 其它: 实例句柄。
spi_event_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_EVENT_TRANSFER_COMPLETE | 传输完成事件 | |
SPI_EVENT_TX_COMPLETE | 发送完成事件 | |
SPI_EVENT_RX_COMPLETE | 接收完成事件 | |
SPI_EVENT_DATA_LOST | 数据丢失事件 | |
SPI_EVENT_MODE_FAULT | 模式错误事件 |
csi_spi_uninitialize
int32_t csi_spi_uninitialize(spi_handle_t handle)
功能描述:
- spi实例反初始化。该接口会停止spi
- 实例正在进行的传输(如果有),并且释放相关的软硬件资源。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_spi_get_capabilities
spi_capabilities_t csi_spi_get_capabilities(int32_t idx)
功能描述:
- 获取spi实例支持的能力。
参数:
idx
: 设备号。
返回值:
- 描述spi能力的结构体,spi 的能力定义见
- spi_capabilities_t定义。
spi_capabilities_t:
名字 | 定义 | 备注 |
---|---|---|
simplex :1 | 支持单向传输模式,即半双工模式(主模式或从模式) | |
ti_ssi :1 | 支持同步串行接口(SSI)工业通信接口 | |
microwire :1 | 支持Microwire串行接口 | |
event_mode_fault :1 | 信号模式故障事件 |
csi_spi_send
int32_t csi_spi_send(spi_handle_t handle, const void *data, uint32_t num)
功能描述:
- spi启动数据发送。
参数:
handle
: 实例句柄。data
: 待发送数据的缓冲区地址。num
: 待发送数据的长度。
返回值:
- 错误码。
csi_spi_receive
int32_t csi_spi_receive(spi_handle_t handle, void *data, uint32_t num)
功能描述:
- spi启动数据接收。
参数:
handle
: 实例句柄。data
: 待接收数据的缓冲区地址。num
: 待接收数据的长度。
返回值:
- 错误码。
csi_spi_transfer
int32_t csi_spi_transfer(spi_handle_t handle, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
功能描述:
- spi启动数据传输。
参数:
handle
: 实例句柄。data_out
: 待发送数据的缓冲区地址。data_in
: 待接收数据的缓冲区地址。num_out
: 待发送数据的长度。num_in
: 待接收数据的长度。
返回值:
- 错误码。
csi_spi_abort_transfer
int32_t csi_spi_abort_transfer(spi_handle_t handle)
功能描述:
- spi数据传输终止。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_spi_get_status
spi_status_t csi_spi_get_status(spi_handle_t handle)
功能描述:
- 获取当前时刻spi的状态。
参数:
handle
: 实例句柄。
返回值:
- spi状态的结构体,spi的状态定义见 spi_status_t的定义。
spi_status_t:
名字 | 定义 | 备注 |
---|---|---|
busy : 1 | 传输或发送忙状态位 | |
data_lost : 1 | 数据丢失 | |
mode_fault : 1 | 模式错误 |
csi_spi_config_mode
int32_t csi_spi_config_mode(spi_handle_t handle, spi_mode_e mode)
功能描述:
- 配置spi 实例的主从工作模式。
参数:
handle
: 实例句柄。mode
: spi的主从模式,参看spi_mode_e的定义。
返回值:
- 错误码。
spi_mode_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_MODE_INACTIVE | spi闲置 | |
SPI_MODE_MASTER | spi全双工主模式 | |
SPI_MODE_SLAVE | spi全双工从模式 | |
SPI_MODE_MASTER_SIMPLEX | spi半双工主模式 | |
SPI_MODE_SLAVE_SIMPLEX | spi半双工从模式 |
csi_spi_config_block_mode
int32_t csi_spi_config_block_mode(spi_handle_t handle, int32_t flag)
功能描述:
- 配置spi 实例的阻塞模式。
参数:
handle
: 实例句柄。flag
: 1:开启block模式;0:关闭block模式
返回值:
- 错误码。
csi_spi_config_baudrate
int32_t csi_spi_config_baudrate(spi_handle_t handle, uint32_t baud)
功能描述:
- 配置spi 实例的速率。
参数:
handle
: 实例句柄。baud
: spi的波特率。
返回值:
- 错误码。
csi_spi_config_bit_order
int32_t csi_spi_config_bit_order(spi_handle_t handle, spi_bit_order_e order)
功能描述:
- 配置spi 实例的数据传输模式。
参数:
handle
: 实例句柄。order
: spi的数据传输模式,参看spi_bit_order_e的定义。
返回值:
- 错误码。
spi_bit_order_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_ORDER_MSB2LSB | 高位(MSB)在前,低位(LSB)在后 | |
SPI_ORDER_LSB2MSB | 低位(LSB)在前,高位(MSB)在后 |
csi_spi_config_datawidth
int32_t csi_spi_config_datawidth(spi_handle_t handle, uint32_t datawidth)
功能描述:
- 配置spi 实例的工作模式。
参数:
handle
: 实例句柄。datawidth
: spi的数据位宽。
返回值:
- 错误码。
csi_spi_config_format
int32_t csi_spi_config_format(spi_handle_t handle, spi_format_e format)
功能描述:
- 配置spi 实例的极性和相位模式。
参数:
handle
: 实例句柄。format
: spi的工作模式,参看 spi_format_e的定义。
返回值:
- 错误码。
spi_format_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_FORMAT_CPOL0_CPHA0 | 空闲电平为低电平,第1个时钟沿采样 | |
SPI_FORMAT_CPOL0_CPHA1 | 空闲电平为低电平,第2个时钟沿采样 | |
SPI_FORMAT_CPOL1_CPHA0 | 空闲电平为高电平,第1个时钟沿采样 | |
SPI_FORMAT_CPOL0_CPHA1 | 空闲电平为高电平,第2个时钟沿采样 |
csi_spi_config_ss_mode
int32_t csi_spi_config_ss_mode(spi_handle_t handle, spi_ss_mode_e ss_mode)
功能描述:
- 配置spi 实例的从设备选择模式。
参数:
handle
: 实例句柄。ss_mode
: spi的从设备使能模式,参看:spi_ss_mode_e的定义。
返回值:
- 错误码。
spi_ss_mode_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_SS_MASTER_UNUSED | 从设备使能主模式未使能 | |
SPI_SS_MASTER_SW | 从设备使能主模式软件模式 | |
SPI_SS_MASTER_HW_OUTPUT | 从设备使能主模式硬件输出模式 | |
SPI_SS_MASTER_HW_INPUT | 从设备使能主模式硬件输入模式 | |
SPI_SS_SLAVE_HW | 从设备使能从模式硬件模式 | |
SPI_SS_SLAVE_SW | 从设备使能从模式软件模式 |
csi_spi_get_data_count
uint32_t csi_spi_get_data_count(spi_handle_t handle)
功能描述:
- 获取设备实例的上一次传输的数据个数。
参数:
handle
: 实例句柄。
返回值:
- 上一次传输的数据个数。
csi_spi_power_control
int32_t csi_spi_power_control(spi_handle_t handle, csi_power_stat_e state)
功能描述:
- 配置设备实例的功耗模式。
参数:
handle
: 实例句柄。state
: 设备实例的功耗模式,参看- csi_power_stat_e \<csi_power_stat_e\ * 的定义。
返回值:
- 错误码。
csi_spi_ss_control
int32_t csi_spi_ss_control(spi_handle_t handle, spi_ss_stat_e stat)
功能描述:
- 控制从设备实例的选择信号状态。
参数:
handle
: 实例句柄。stat
: 设备选择信号状态,见 spi_ss_stat_e定义。
返回值:
- 错误码。
spi_ss_stat_e:
名字 | 定义 | 备注 |
---|---|---|
SPI_SS_INACTIVE | 从设备选择信号无效 | |
SPI_SS_ACTIVE | 从设备选择信号有效 |
示例
SPI示例1
static spi_handle_t spi_handle;
static void spi_event_cb_fun(int32_t idx, spi_event_e event)
{
//do your job here according to event
}
void example_main(void)
{
spi_capabilities_t cap;
int32_t ret;
uint8_t send_buf[8] ={0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8};
uint8_t recv_buf[8];
uint8_t i;
spi_handle = csi_spi_initialize(1,spi_event_cb_fun);
if (spi_handle == NULL) {
//fail
return;
}
ret = csi_spi_power_control(spi_handle, DRV_POWER_FULL);
if (ret < 0) {
// power control failed
return;
}
//get spi capabilities
cap = csi_spi_get_capabilities(1);
printf("spi %s simplex mode\n",cap.simplex==1 ? "supports":"not supports");
printf("spi %s TI Synchronous Serial Interface\n",cap.ti_ssi==1 ? "supports":
"not supports");
printf("spi %s Microwire Interface\n",cap.microwire==1 ? "supports":"not supports");
printf("spi %s signal mode fault event\n",cap.event_mode_fault==1 ? "have":
"have not");
//config spi as: baud 115200,master mode ,mode= 0,MSB2LSB, 7bit
ret = csi_spi_config_mode(spi_handle, SPI_MODE_MASTER);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_block_mode(spi_handle, 1);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_baudrate(spi_handle, 115200);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_datawidth(spi_handle, 8);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_bit_order(spi_handle, SPI_ORDER_MSB2LSB);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_format(spi_handle, SPI_FORMAT_CPOL0_CPHA0);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_send(spi_handle, send_buf, sizeof(send_buf));
if (ret < 0) {
//send data failed
return;
}
//check send result here
ret = csi_spi_receive(spi_handle, recv_buf, sizeof(recv_buf));
if (ret < 0) {
//receive data failed
return;
}
//check receive result here
for (i = 0; i < sizeof(send_buf); i++) {
if (send_buf[i] != recv_buf[i]) {
// send and receive data failed
return;
}
}
ret = csi_spi_power_control(spi_handle, DRV_POWER_OFF);
if (ret < 0) {
// power control failed
return;
}
//uninitialize spi
ret = csi_spi_uninitialize(spi_handle);
if (ret != 0) {
//failed
}
}
SPI示例2
static spi_handle_t spi_handle;
static void spi_event_cb_fun(int32_t idx, spi_event_e event)
{
//do your job here according to event
}
void example_main(void)
{
int32_t ret;
uint8_t send_buf[8] ={0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8};
uint8_t recv_buf[8];
uint8_t i;
spi_handle = csi_spi_initialize(1, spi_event_cb_fun);
if (spi_handle == NULL) {
//failed
return;
}
ret = csi_spi_power_control(spi_handle, DRV_POWER_FULL);
if (ret < 0) {
// power control failed
return;
}
//config spi as: baud 115200,master mode ,mode= 0,MSB2LSB, 7bit
ret = csi_spi_config_mode(spi_handle, SPI_MODE_MASTER);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_block_mode(spi_handle, 1);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_baudrate(spi_handle, 115200);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_datawidth(spi_handle, 8);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_bit_order(spi_handle, SPI_ORDER_MSB2LSB);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_config_format(spi_handle, SPI_FORMAT_CPOL0_CPHA0);
if (ret < 0) {
//config fail
return ;
}
ret = csi_spi_transfer(spi_handle, send_buf, recv_buf, sizeof(send_buf), sizeof(recv_buf));
if (ret < 0) {
//spi transfer failed
return;
}
for (i = 0; i < sizeof(send_buf); i++) {
if (send_buf[i] == recv_buf[i]) {
// send and receive data should not same
break;
}
}
ret = csi_spi_power_control(spi_handle, DRV_POWER_OFF);
if (ret < 0) {
// power control failed
return;
}
//uninitialize spi
ret = csi_spi_uninitialize(spi_handle);
if (ret != 0) {
//failed
}
}