STM32——软件SPI协议解析

         目录

一、SPI简介        

二、硬件基础

三、SPI基本的通讯单元

0.SPI移位寄存器工作原理:

1.起始条件:

2.终止条件: 

3.交换一个字节:

 四、软件SPI读写STM32F103ZET6板载W25Q16的ID号

1.硬件前提:

2.软件部分: 

1.初始化引脚:

2. 发送9h指令读取ID号。

3.打印在OLED屏幕上:

4.现象:


一、SPI简介        

        SPI的英文全称为Serial Peripheral Interface,是一种通用数据总线。较为重要的端口为MOSI(主机输出,从机输入)、MISO(主机输入,从机输出)、SCL(总线时钟)、CS(片选信号)。

二、硬件基础

        如下图所示,主机的MOSI与从机的SDI(Slave Data Input)相连,主机的MISO与从机的SDO(Slave Data Output),主机片选信号CS与从机片选相连(Chip Select)通常低电平有效,时钟总线相连一起。根据输入输出特性,在软件SPI中,将MOSI、SCL、CS配置为推挽输出将MISO配置成上拉输入即可。

        STM32——软件SPI协议解析_第1张图片

三、SPI基本的通讯单元

0.SPI移位寄存器工作原理:

        SPI主机与从机通讯实际上时两者的移位寄存器交换数据的过程,在时钟信号SCL的推动下,主机发送一位,从机也发送一位,两者互换数据,交换8次之后,便完成了一个字节的传输。

STM32——软件SPI协议解析_第2张图片

STM32——软件SPI协议解析_第3张图片

        代码前提:

void MySPI_W_CS(uint8_t value)
{
    GPIO_WriteBit(SPI_PORT,SPI_CS_PIN,(BitAction)value);
}
void MySPI_W_SCL(uint8_t value)
{
    GPIO_WriteBit(SPI_PORT,SPI_SCL_PIN,(BitAction)value);
}
void MySPI_W_MOSI(uint8_t value)
{
    GPIO_WriteBit(SPI_PORT,SPI_MOSI_PIN,(BitAction)value);
}
uint8_t MySPI_R_MISO(void )
{
    return  GPIO_ReadInputDataBit(SPI_PORT,SPI_MISO_PIN);;
}

1.起始条件:

        片选信号由高至低,即选中从机芯片通讯的过程。

STM32——软件SPI协议解析_第4张图片

void MySPI_Start(void )
{
    MySPI_W_CS(0);
}

2.终止条件: 

        片选信号由低至高,即不选从机芯片的过程。

STM32——软件SPI协议解析_第5张图片

void MySPI_Stop(void )
{
    MySPI_W_CS(1);
}

3.交换一个字节:

        介绍一种最常用的通讯模式:CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。

STM32——软件SPI协议解析_第6张图片

uint8_t MySPI_SwapData(uint8_t Data)
{
    uint8_t temp=0x00;
    for (int i = 0; i < 8; i++)
    {
        MySPI_W_MOSI(Data & (0x80>>i));
        MySPI_W_SCL(1);
        if(MySPI_R_MISO()==1)
        {
            temp|=(0x80>>i);
        }
        MySPI_W_SCL(0);
    }
    return temp;
}

 四、软件SPI读写STM32F103ZET6板载W25Q16的ID号

1.硬件前提:

        多数商家所售STM32F103ZET6自带一块支持SPI通讯的W25Q16,如下图:

        原理图如下:观察可知,所接的PB12、13、14、15也为板上ZET6班上对应的硬件SPI资源,本文中我们使用软件时序模拟SPI。

 STM32——软件SPI协议解析_第7张图片

        本文中我们读出该设备ID号 :查看手册可知:MID为EF(十六进制)DID为4015(十六进制)。

STM32——软件SPI协议解析_第8张图片

2.软件部分: 

1.初始化引脚:

void MySPI_Init(void )
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=SPI_CS_PIN|SPI_SCL_PIN|SPI_MOSI_PIN;
    GPIO_Init(SPI_PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin=SPI_MISO_PIN;
    GPIO_Init(SPI_PORT,&GPIO_InitStructure);

    MySPI_W_CS(1);
    MySPI_W_SCL(0);
}

2. 发送9h指令读取ID号。

void W25Q16_Init(void )
{
    MySPI_Init();
}
void W25Q16_Read_ID(uint8_t* MID,uint16_t* DID)
{
    MySPI_Start();
    MySPI_SwapData(0x9F);
    *MID=MySPI_SwapData(0xFF);
    *DID=MySPI_SwapData(0xFF);
    *DID<<=8;
    *DID|=MySPI_SwapData(0xFF);
    MySPI_Stop();
}

3.打印在OLED屏幕上:

#include "main.h"
static int i=0;
int main(void)
{
    uint8_t MID=0;
    uint16_t DID=0;
    uart_init(115200);
    delay_init();
    OLED_Init();
    OLED_Clear();
    W25Q16_Init();
    W25Q16_Read_ID(&MID,&DID);
    while(1)
    {
            for (; i < 1; ++i) {
                OLED_Init();
                OLED_Clear();
            }
            OLED_ShowString(1,0,"MID:",16);
            OLED_ShowString(1,2,"DID:",16);
            OLED_ShowHexNum(40,0,MID,2);
            OLED_ShowHexNum(40,2,DID,4);
    }
    return 0;
}

4.现象:

        符合最终的现象,正确读出设备ID号!

STM32——软件SPI协议解析_第9张图片

你可能感兴趣的:(网络,stm32,嵌入式硬件)