最近在使用esp32驱动一个spi设备的时候,spi设备没有应答,奇怪的时候我之前用stm32成功驱动过这个spi设备,怎么移植到esp32就不行呢?
在使用stm32的时候我是使用spimode3,即CPOL=1, CPHA=1,参考通用的spi模式定义:
spi四种模式SPI的相位(CPHA)和极性(CPOL)分别可以为0或1,对应的4种组合构成了SPI的4种模式(mode)
Mode 0 CPOL=0, CPHA=0
Mode 1 CPOL=0, CPHA=1
Mode 2 CPOL=1, CPHA=0
Mode 3 CPOL=1, CPHA=1
时钟极性CPOL: 即SPI空闲时,时钟信号SCLK的电平(1:空闲时高电平;
0:空闲时低电平)
时钟相位CPHA: 即SPI在SCLK第几个边沿开始采样(0:第一个边沿开始;
1:第二个边沿开始)
时序图如下:
文章图片
在esp32上面我也应该使用mode3的,最后我改esp32的spi模式=SPI_MODE2的时候协议分析仪获取到的数据才是正确的,都有点让我怀疑人生了。难道标准规范不对?
SPI.begin(sck, miso, mosi, cs);
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE2));
或者esp32没有根据通用规范来标识,查看esp32的底层驱动文件发现真是这样:
源文件名称:esp32-hal-spi.c
void spiSetDataMode(spi_t * spi, uint8_t dataMode)
{
if(!spi) {
return;
}
SPI_MUTEX_LOCK();
switch (dataMode) {
case SPI_MODE1:
spi->dev->pin.ck_idle_edge = 0;
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE2:
spi->dev->pin.ck_idle_edge = 1;
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE3:
spi->dev->pin.ck_idle_edge = 1;
spi->dev->user.ck_out_edge = 0;
break;
case SPI_MODE0:
default:
spi->dev->pin.ck_idle_edge = 0;
spi->dev->user.ck_out_edge = 0;
break;
}
SPI_MUTEX_UNLOCK();
}
原来esp32是用“SPI_MODE2”来代表:
CPOL=1, CPHA=1
至此真相大白,看来有时候必须追根问底才能得到真理。
参考资料:
【1】SPI四种模式区别
【2】 linux spi驱动开发学习(三)-----spi_bitbang.c详解
【esp32的spi驱动的编写遇到的问题】【3】 github源文件:arduino-esp32/cores/esp32/esp32-hal-spi.c