SPI简介
SPI 协议是由Motorola提出的通讯协议 (Serial Peripheral Interface) ,是一种高速全双工的串行通信总线。
SPI 通讯使用 3 条总线 :SCK、 MOSI、 MISO ,以及若干片选线(SS、CS、NSS)。
主机要和哪个从机通信,就把对应的片选线拉低,由高变低是起始信号,由低边高是停止信号。
CPOL/CPHA 及通讯模式
时钟极性 CPOL 是指 空闲状态时SCK 的电平信号。CPOL=0 时, SCK 在空闲状态为低电平, CPOL=1 时则反之。
时钟相位 CPHA 是指数据的采样的时刻。当 CPHA=0 时, 信号将会在SCK 时钟线的**“奇数边沿”**被采样, CPOL=1 时则反之。
所以SPI就有4种通讯模式,实际中采用较多的是“模式 0”与“模式 3”
模式 | CPOL | CPHA | SCK空闲状态 | 采样时刻 |
---|---|---|---|---|
0 | 0 | 0 | 低电平 | 奇数边沿 |
1 | 0 | 1 | 低电平 | 偶数边沿 |
2 | 1 | 0 | 高电平 | 奇数边沿 |
3 | 1 | 1 | 高电平 | 偶数边沿 |
实例分析
逻辑分析仪图示
已知:SPI使用的是模式1,输入的数据是0x58 0x03,收到的数据是0x00 0x00 0x00 0xA4,和图示完全符合。
图片可能不太好放大看,文末提供源文件。
相关实验代码(ESP32)
void bl0942_init()
{
esp_err_t ret;
static spi_bus_config_t buscfg={
.miso_io_num = PIN_NUM_MISO,
.mosi_io_num = PIN_NUM_MOSI,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 1024
};
// 初始化spi
ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
ESP_LOGI(TAG, "spi_bus_initialize = %d", ret);
static spi_device_interface_config_t devcfg={
.clock_speed_hz = 500 * 1000,
.mode = 1,
.spics_io_num = -1, // 不使用片选
.queue_size = 7,
.pre_cb = NULL //传输前的回调
};
// 添加从设备
ret = spi_bus_add_device(SPI2_HOST, &devcfg, &gw_spi);
ESP_LOGI(TAG, "spi_bus_add_device = %d", ret);
}
int bl0942_spi_r(uint8_t ICAddr, uint8_t cmd)
{
int ret;
uint8_t CHECKSUM = 0;
spi_transaction_t t;
memset(spi_tx_buf, 0, sizeof(spi_tx_buf));
spi_tx_buf[0] = ICAddr;
spi_tx_buf[1] = cmd;
memset(&t, 0, sizeof(t));
t.length = 8 * 6;
t.tx_buffer= spi_tx_buf;
t.rx_buffer= spi_rx_buf;
t.user=(void*)0;
ret = spi_device_polling_transmit(gw_spi, &t);
if (ret != 0)
{
ESP_LOGE(TAG, "spi_device_polling_transmit err");
return -1;
}
return 0;
}
void bl0942_read_all()
{
bl0942_spi_r(0x58, 0x03);
ESP_LOG_BUFFER_HEX(TAG, spi_rx_buf+2, 4);
// 00 00 00 a4
}
逻辑分析仪源文件
逻辑分析仪型号:Kingst LA1010
软件与源文件点击下载