STM32 SPI协议

SPI是一种串行,全双工,同步通信总线

我们先解释下这几个名词,其实在前面的IIC USART中都有出现

串行:要发的数据排成一排,一个(位)一个(位)的发,

并行:要发的数据排成一排(8个或者16、32),一排一起发

 

单工:单方向的接收或发送,比如电视

半双工:可以接也可以发,但是同一时间一方只能选择 接 或者 发,比如对讲机

全双工:收发信息是独立的,互不影响。比如电话

 

同步:发送方和接收方用相同频率的时钟(有时钟线 比如IIC 和本文的SPI)

异步:时钟并不是相同的,所以在每一次发送数据的时候,需要有开始位和停止位

 

 

根线MOSI(SDO)  MISO(SDI)  SCLK  SS(CS)     (可能还会存在地线GND)

MOSI 主设备输出 从设备输入 最大速度复用推挽输出

MISO 主设备输入 从设备输出 上下拉输入

SCLK 时钟线 只能由主设备输出 最大速度复用推挽输出

NSS 选择主从设备 每个从设备可以选择自己的NSS

 

 

SPI有种工作方式:

通过配置CR1中的CPHA、CPOL从而选择不同的工作方式

CPOL = 1 空闲是高电平;CPOL = 0 空闲是低电平

CPHA = 0 第一个跳变时采样;CPHA = 1 第二个跳变时采样

(在本文后面的示例代码中选择第一种工作方式)

 

 

 

在SPI通信中,没有读和写的说法,它使用的是主从模式,你发出数据了,那就必然会收到数据回来,你要想收到数据,那你必须要先发出数据。

因为SPI是串行同步通信,所以需要有一根时钟线,去提供脉冲频率

在通信当中,时钟线的作用就类似于你军训时教官喊的口令121121,由时钟线告诉你,1 和 0 应该怎么发。

 

 

 

 

代码如下 这是cotex-M3使用的代码

/*
函数功能:SPI2接口初始化
*/
void Spi2_Pin_Init(void)
{
    //IO功能配置
    RCC->APB2ENR |=0x01<<3;
    GPIOB->CRH &=~(0xFFF<<20);
    GPIOB->CRH |=(0xB8B<<20);
        
    RCC->APB1ENR |=1<<14;  //SPI2时钟使能
    SPI2->CR1 &=~(1<<11); //8位数据帧
    SPI2->CR1 |=1<<9;  //
    SPI2->CR1 |=1<<8;  //
    SPI2->CR1 &=~(1<<7);  //先发高位
    SPI2->CR1 &=~(0x7<<3);  
    SPI2->CR1 |=0x0<<3;  //波特率
    
    //从四种工作模式中选择一种
    SPI2->CR1 |=1<<1;  //时钟空闲状态为高电平
    SPI2->CR1 |=1<<0;  //在时钟第二个电平发送数据
    
    SPI2->CR1 |=1<<2; //主SPI
    
    SPI2->CR1 |=1<<6;     //使能SPI
    Spi2_Transfer_Byte(0xff);
}

/*
函数功能:主机发送一个字节给从机
注意事项:MODE0/3
*/
void Spi2_Send_Byte(u8 data)
{
    u8 i;
    GPIOB->ODR |= 0X1 <<13;                //SCLK=1
    for(i=0;i<8;i++)
    {
        GPIOB->ODR &= ~(0X1 <<13);        //SCLK=0//准备数据
        if(data&0x80) 
        {
            GPIOB->ODR |= (0X1 <<15);    //MOSI=1;
        }
        else 
        {
            GPIOB->ODR &= ~(0X1 <<15)    //MOSI=0;
        }
        GPIOB->ODR |= 0X1 <<13;            //SCLK=1
        data<<=1;//让次高位变成最高位
    }
}


u8 Spi2_Transfer_Byte(u8 data)
{
    while(!(SPI2->SR&(0x01<<1)));            //TXE transmit buffer empty
    SPI2->DR=data;                    //在数据寄存器中写入数据
    while(!(SPI2->SR&(0x01<<0)));            //PXNE receive buffer not empty
    return     SPI2->DR;
}

 

posted @ 2019-10-28 16:40  祁峰_1024  阅读(490)  评论(0编辑  收藏  举报