SPI通讯的个人理解

SPI一共有四根信号线CS、CLK、MOSI、MISO  从设备选择信号线、串行SPI通信的时钟信号、主设备输出从设备输入、主设备输入从设备输出信号线。在硬件上主设备和从设备的两条数据线MOSI和MISO要相互交叉连接(个人理解成串口通信时的TX发接RX,RX接TX)。SPI的数据采集和传输依赖于CLK,一个周期的时钟移动一个位的数据。下面是SPI的时序图,从图中可以看出CPHA和CPOL的作用和意义。

SPI的时序图

 从SPI的时序图可以明显的看出CPHA的作用是控制数据采样的点如CPHA=1时数据在跳变后一个时钟采样,上升沿采样还是下降沿采样数据由CPOL决定(也决定了CLK空闲时刻的电平情况)。所以我们在使用单片机自带的硬件SPI的时候这些配置就很重要了,这关系到是否能通讯成功。

SPI的配置一般有以下步骤:1、配置SPI的硬件SPI相应的引脚。2、开启GPIO时钟和SPI时钟。3、配置SPI的主从模式。4、配置SPI的CPHA和CPOL。5、配置SPI的数据宽度。6、配置SPI的移位是LSB或者是MSB。7、配置SPI的传输速度。8、如有多个SPI的一半还有SPI的选择配置。一般大致就是这些就基本OK了。

下面是谋产品的SPI的通信时序图。

 从该图给出的时序图就知道需要配置CPHA=1,CPOL=0;即时钟空闲的时候为低电平状态,当被主设备选中CS拉低之后的时钟在跳变后的下降沿采样数据。

当然在编写SPI的读写程序的时候也需要注意一点,写数据的时候将数据放到SPI的发送寄存器的时候会自动产生硬件的时钟CLK和数据写的电平。但是读数据的时候需要SPI主设备的发送空数据来产生时钟使从设备的数据移位到主设备中。

SPI的读写程序:

void SPI_write(u8 addr, u32 data,u8 len)
{
    uint8_t i,B;
    GPIO->PBCLR =1<<4;
    SPI->STA |=0<<0; 
    SPI->TX = (1<<7)|(0XFF&addr);  //起始第一位为1是写数据
    while(SPI->STA&0X10);
    
    for(i=len;i>0;i--)
    {
        B=(data>>8*(i-1));
        SPI->STA |=0<<0; 
        SPI->TX = 0XFF&B;
        while(SPI->STA&0X10);    
    }
    
    GPIO->PBSET = 1<<4;
}


u32 SPI_Read(u8 addr,u8 len)
{
    uint32_t ReadData,B;
    uint8_t i;
    
    GPIO->PBCLR =1<<4;
    SPI->STA |=0<<0; 
    SPI->TX = 0Xff&addr;
    while(SPI->STA&0X10);
    
    for(i=0;i<len;i++)
    {
        SPI->STA |=0<<0; 
        SPI->TX = 0Xff;  //读从设备数据的时候发送空数据产生时钟CLK
        while(SPI->STA&0X10);
        ReadData = (ReadData <<8)|(SPI->RX &0XFF);  //数据移位
    }
    
    GPIO->PBSET = 1<<4;
    return ReadData;
}

记录自己对SPI的理解。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于SCl3300传感器是SPI接口的设备,因此需要使用ESP32的SPI库来实现数据传输。以下是基于ESP32的Arduino环境下,使用SPI库实现SCl3300传感器数据传输的示例代码: ``` #include <SPI.h> #define SCL3300_CS_PIN 19 SPISettings settings(1000000, MSBFIRST, SPI_MODE0); void setup() { Serial.begin(115200); SPI.begin(); pinMode(SCL3300_CS_PIN, OUTPUT); } void loop() { byte data[3]; digitalWrite(SCL3300_CS_PIN, LOW); SPI.beginTransaction(settings); SPI.transfer(0x20); // send read command data[0] = SPI.transfer(0x00); data[1] = SPI.transfer(0x00); data[2] = SPI.transfer(0x00); SPI.endTransaction(); digitalWrite(SCL3300_CS_PIN, HIGH); int x = (data[0] << 8) | data[1]; int y = (data[2] << 8); Serial.print("X: "); Serial.print(x); Serial.print(" Y: "); Serial.println(y); delay(1000); } ``` 在此示例代码中,我们首先定义了SCl3300传感器的CS引脚为19号引脚,并且使用了SPI库中的SPISettings来配置SPI传输的速度、传输模式等参数。在setup函数中,我们初始化了Serial和SPI,并将CS引脚设置为输出模式。 在loop函数中,我们定义了一个长度为3的字节数组data来存储从SCl3300传感器读取到的数据。然后我们将CS引脚拉低,开始传输数据。在传输数据之前,我们需要调用SPI.beginTransaction函数来设置传输参数。然后我们首先发送读取命令0x20,然后连续读取3个字节的数据,分别存储到data数组中。SPI传输完成后,我们将CS引脚拉高,结束传输。 最后,我们将data数组中的数据解析为X和Y轴的值,并打印输出到串口监视器中。此时,我们可以通过串口监视器观察SCl3300传感器的输出值,并调整程序中的参数以实现不同的数据处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值