STM32 SPI 模拟实现 W25X16读写 代码

原创 2017年06月18日 17:10:35

本文主要是为了针对 SPI 通讯的深入了解,加强基本工的练习。希望对大家有用!联系方式:QQ:279894340 

想要原代码的可以到我的博客下载。谢谢

一、SPI总线协议及SPI时序图详解:

SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
      SPI是一个环形总线结构,由ss(cs)、sck、sdi、sdo构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。
    上升沿发送、下降沿接收、高位先发送。
    上升沿到来的时候,sdo上的电平将被发送到从设备的寄存器中。
    下降沿到来的时候,sdi上的电平将被接收到主设备的寄存器中。
    假设主机和从机初始化就绪:并且主机的sbuff=0xaa (10101010),从机的sbuff=0x55 (01010101),下面将分步对spi的8个时钟周期的数据情况演示一遍(假设上升沿发送数据)。
---------------------------------------------------
脉冲           主机sbuff    从机sbuff     sdi    sdo(到从设备)
---------------------------------------------------
0    00-0     10101010     01010101      0      0
---------------------------------------------------
1    0--1     0101010x     10101011      0      1
1    1--0     01010100     10101011      0      1
---------------------------------------------------
2    0--1     1010100x     01010110      1      0
2    1--0     10101001     01010110      1      0
---------------------------------------------------
3    0--1     0101001x     10101101      0      1
3    1--0     01010010     10101101      0      1
---------------------------------------------------
4    0--1     1010010x     01011010      1      0
4    1--0     10100101     01011010      1      0
---------------------------------------------------
5    0--1     0100101x     10110101      0      1
5    1--0     01001010     10110101      0      1
---------------------------------------------------
6    0--1     1001010x     01101010      1      0
6    1--0     10010101     01101010      1      0
---------------------------------------------------
7    0--1     0010101x     11010101      0      1
7    1--0     00101010     11010101      0      1
---------------------------------------------------
8    0--1     0101010x     10101010      1      0
8    1--0     01010101     10101010      1      0全双工通讯,一次传2个字节
---------------------------------------------------

    这样就完成了两个寄存器8位的交换,上面的0--1表示上升沿、1--0表示下降沿,sdi、 sdo相对于主机而言的。根据以上分析,一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的名准备数据,主机在下一个8位时钟周期才把数据读回来。
    SPI总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于 CPU与各种外围器件进行全双工、同步串行通讯。SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。


/*********************************************************************************************************

** 宏定义
*********************************************************************************************************/ 
#define SPI_CSHIGH  GPIO_SetBits(GPIOB,GPIO_Pin_9)  // CS----PB9
#define SPI_CSLOW   GPIO_ResetBits(GPIOB,GPIO_Pin_9)  
  
#define SPI_SCKHIGH GPIO_SetBits(GPIOA,GPIO_Pin_5)    //SCLK----PA5
#define SPI_SCKLOW  GPIO_ResetBits(GPIOA,GPIO_Pin_5)  

#define SPI_OUTHIGH GPIO_SetBits(GPIOA,GPIO_Pin_7)  
#define SPI_OUTLOW  GPIO_ResetBits(GPIOA,GPIO_Pin_7)  //MOSI----PA7

#define SPI_IN      GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)  //MISO----PA6

/**********************************************************************
* Function:  SPI_SendData
* Description:  
*               
* Input:      void
* Output:    
* Return:  RecevieData  :接收到的数据
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping         
**********************************************************************/
static uint8_t SPI_SendData(uint8_t data)  
{  
    uint8_t RecevieData=0,i;  

    for(i=0;i<8;i++)  
    {  
        if(data&0x80)  
        {  
            SPI_OUTHIGH;  
        }  
        else  
        {  
            SPI_OUTLOW;  
        }  

      SPI_SCKHIGH;              //我这里是选择下降沿采集数据
       data<<=1; 
     __NOP();__NOP();__NOP();__NOP(); 
     RecevieData <<= 1;

        if(SPI_IN)
        {
            RecevieData |= 1; //Wait SDO to go Hi
        }
       SPI_SCKLOW;          
    }  
    return RecevieData;  
}

/**********************************************************************
* Function:  MYSPI_Init
* Description:  初始化GPIO口
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping         
**********************************************************************/
static void MYSPI_Init(void)  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA ,ENABLE);                      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7; //SPI_CS  and SPI_SCK and SPI_OUT  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_Init(GPIOA,&GPIO_InitStructure);  

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //SPI_IN  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  
    GPIO_Init(GPIOA,&GPIO_InitStructure);  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //SPI_CS  and SPI_SCK and SPI_OUT  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_Init(GPIOB,&GPIO_InitStructure);  
    SPI_CSHIGH;  
    SPI_SCKLOW;  
    SPI_OUTLOW;  
}

/**********************************************************************
* Function:  SPI_Delay
* Description:  
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping          
**********************************************************************/
static void SPI_Delay(void)  
{  
    uint16_t i;  

    for(i=0;i<72;i++);  

/**********************************************************************
* Function:  W25x16_WriteEnable
* Description:  
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping          
**********************************************************************/
void W25x16_WriteEnable(void)  
{  
    SPI_CSLOW;  
    SPI_SendData(0x06);  
    SPI_CSHIGH;  
    SPI_Delay();  

/**********************************************************************
* Function:  W25x16_BlockErase
* Description:  SectorErase  64K Byte 
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping         
**********************************************************************/
void W25x16_BlockErase(uint16_t addr)  
{  
    W25x16_WriteEnable();  
    SPI_CSLOW;  
    SPI_SendData(0xD8);  
    SPI_SendData((addr>>16)&0xFF);
    SPI_SendData((addr>>8)&0xFF);  
    SPI_SendData(addr&0xFF);  
    SPI_CSHIGH;  
}  

/**********************************************************************
* Function:  W25x16_ReadDeviceID
* Description:  读取设备ID
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping         
**********************************************************************/
uint32_t W25x16_NewReadDeviceID(void)  
{  
    uint8_t ret;  

   u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

    SPI_CSLOW;  
    SPI_SendData(0x9F);  
    Temp0 = SPI_SendData(0xff);  
    Temp1 = SPI_SendData(0xff);  
    Temp2 = SPI_SendData(0xff);  
    SPI_CSHIGH;  
    Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
    return Temp;  


uint8_t WriteBuf[10] = {0xAA, 0xBB, 0x45, 0x78, 0x34, 0x78, 0x89,0xAC, 0xBC, 0xDD};  
uint8_t RreadBuf[10] = {0};  
void W25x16_test(void)  

    W25x16_SectorErase(0x0000);
        W25x16_WritePage(0x0000, WriteBuf, 10);  
W25x16_ReadData(0x0000, RreadBuf, 10);
}

/**********************************************************************
* Function:  W25x16_Init
* Description:  初始化设备ID  
*               
* Input:      void
* Output:    
* Return:    void 
* Others:  
* Modify Date:    Version:    Author:      Modification:
* -----------------------------------------------
* 2017-06-22  V1.0     Hu Weiping         
**********************************************************************/  
__IO uint32_t numID = 0;


void W25x16_Init(void)  
{  
MYSPI_Init();  
numID = W25x16_NewReadDeviceID();   //这里可以查看到W25X16  ID 
W25x16_test();  
       while(1);
}

2M字节Flash Rom存储器W25Q16/W25X16 认识Flash

原地址:http://www.51hei.com/bbs/dpj-41029-1.html 认识Flash Rom FlashRom 是快速擦写只读存储器,也就是我...
  • AI_yantinghao
  • AI_yantinghao
  • 2017年06月29日 14:22
  • 1958

W25X16中文资料

  • 2017年05月14日 08:24
  • 1.35MB
  • 下载

w25x16中文手册

  • 2013年07月05日 15:35
  • 863KB
  • 下载

STM32 的SPI读写函数解析

//SPIx 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPIx_ReadWriteByte(u8 TxData) {           ...
  • a827415225
  • a827415225
  • 2017年06月21日 09:25
  • 1495

STM32学习笔记之硬件SPI读写与极性设置

大家介绍SPI,用的是战舰的教程,文中标红的是特别注意看的地方主要是熟悉flash芯片的指令集,以及存储芯片扇区和块的理解,最重要的是擦除都是以扇区擦除的方式。 本节将利用SPI来实现对外部FLAS...
  • sinat_23338865
  • sinat_23338865
  • 2016年08月31日 21:54
  • 7239

STM32_SPI读写Flash

今天讲解“STM32F103 SPI读写Flash”,其实这第一阶段主要是讲解STM32的SPI功能,所有今天的重点是SPI,关于FLASH我应该要在后面再次讲述。 今天提供并讲解的软件工程,基于软件...
  • ybhuangfugui
  • ybhuangfugui
  • 2016年05月09日 20:42
  • 12522

STM32系统学习——SPI(读写串行 FLASH)

一、SPI 协议简介 SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADC、...
  • zxh1592000
  • zxh1592000
  • 2017年12月09日 16:55
  • 151

stm32 SPI 收发数据

STM32-SPI使用 SPI知识: 1) 高速同步串行口。3~4线接口(CS ,CLK ,MOSI,MISO),收发独立、可同步进行。 2)SPI分为主从模式,主模式提供时钟和片选选择信号....
  • zc850463390zc
  • zc850463390zc
  • 2012年10月22日 17:26
  • 17009

普通GPIO模拟SPI通信协议(软件SPI)

在工作中偶尔会遇到SPI不够用的情况,而我们又要去使用SPI通信协议,此时就需要我们自己去模拟SPI通信协议。我们知道SPI通信协议有四种模式,它们分别如下所示: 下面是我基于ATSAM4SD1...
  • Andy001847
  • Andy001847
  • 2016年12月29日 09:46
  • 4073

GPIO口模拟SPI - 驱动W25Qxx

废话少说,直接上代码: DataFlash_reg.h:/* Using SPIO simulator PB8 -- spi cs PA9 -- spi clock PA10 -- spi MO...
  • EFM32
  • EFM32
  • 2016年01月11日 22:26
  • 4052
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STM32 SPI 模拟实现 W25X16读写 代码
举报原因:
原因补充:

(最多只允许输入30个字)