2019年9月21日星期六(STM32 spi接口flash)

一.Flash

1.内置Flash编程访问

(1)在擦除和写flash必须先解锁,操作完后加锁

    FLASH_Unlock();//解锁

    FLASH_Lock();//加锁

(2)在读/写Flash之前应该清除错误标识

    FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_OPERR|FLASH_FLAG_WRPERR|

                    FLASH_FLAG_PGAERR|FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

(3)擦除和写操作

    FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange)

    参数:

        FLASH_Sector - 哪个扇区

        VoltageRange - 电压范围

    返回 FLASH_COMPLETE 表示擦除成功

    FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)

    参数:

        Address - 写的地址

        Date - 写的数据

    返回 FLASH_COMPLETE 表示写成功

(4)读操作

    Flash的读操作非常简单,直接把要读的Flash地址当做内存地址访问就可以了

练习:

    通过蓝牙读取温度,将温度和读取时间保存到flash

二.SPI

1.概念和总线结构

    SPI是Serial Peripheral interface的缩写,就是串行外设接口。是摩托罗拉公司设计的。SPI接口主要应用在eeprom flash rtc时钟 AD转换器,数字信号处理器等等外设和CPU之间的通信

    SPI是高速,全双工,同步的串行总线(一主多从),数据传输需要四根线

        SDI:串行数据输入

        SDO:串行数据输出

        SCK:时钟线

        CS:从设备使能

 2019年9月21日星期六(STM32 spi接口flash)

为了区分主设备和从设备的传输方向,我们通常以以下方式命名

    MISO(master input slave output):主设备输入,从设备输出

    MOSI(master output slave input):主设备输出,从设备输入

    SCLK:时钟信号线,主设备控制

    CS:从设备片选信号线,主设备控制

2.通信原理

2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

    传输时序可以使用IO口模拟实现,也可以使用SPI控制器实现

3.时钟的相位和极性

(1)时钟极性

    决定时钟线的默认电平

    CPOL = 1 默认高电平

    CPOL = 0 默认低电平

(2)时钟相位

    决定第几个边沿读写

    CPHA = 1 在第二个边沿进行采样

    CPHA = 0 在第一个边沿进行采样

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

4.stm32f407的SPI控制器

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 三.SPI Flash -------- W25Q128

1.原理图

2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2.w25q128的说明手册

(1)高地位顺序和极性

    MSB

    mode = 0(默认低电平)

    mode = 1(默认高电平)

    2019年9月21日星期六(STM32 spi接口flash)

    上升沿input 下降沿output

(2)状态寄存器1和2

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

(3)芯片操作

 2019年9月21日星期六(STM32 spi接口flash)

   2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

 2019年9月21日星期六(STM32 spi接口flash)

3.SPI控制器编程

(1)开启SPI和GPIO时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    ....

(2)将GPIO配置成复用功能(片选脚配置为输出)

    GPIO_Init(...);

(3)将IO口复用映射为SPI功能

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3,GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource4,GPIO_AF_SPI1);    

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource4,GPIO_AF_SPI1);

(4)SPI初始化

    void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)

    参数:

        SPIx - 哪个SPI

        SPI_InitStruct - 初始化结构

 typedef struct
{
  uint16_t SPI_Direction;           /*!< 传输方式 全双工 SPI_Direction_2Lines_FullDuplex @ref SPI_data_direction */

  uint16_t SPI_Mode;                /*!< 主/从模式 SPI_Mode_Master @ref SPI_mode */

  uint16_t SPI_DataSize;            /*!< 数据长度 SPI_DataSize_8b @ref SPI_data_size */

  uint16_t SPI_CPOL;                /*!< 极性 SPI_CPOL_Low ? @ref SPI_Clock_Polarity */

  uint16_t SPI_CPHA;                /*!< 相位 SPI_CPHA_1Edge ?@ref SPI_Clock_Phase */

  uint16_t SPI_NSS;                 /*!< 片选选择 SPI_NSS_Soft @ref SPI_Slave_Select_management */
 
  uint16_t SPI_BaudRatePrescaler;   /*!< 预分频系数 SPI_BaudRatePrescaler_16 */

  uint16_t SPI_FirstBit;            /*!< 高地位顺序 SPI_FirstBit_MSB */

  uint16_t SPI_CRCPolynomial;       /*!< CRC校验,不使用 */
}SPI_InitTypeDef;

(5)使能SPI1

    SPI_Cmd(SPI1,ENABLE);


(6)发送和接收数据

    uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)

    void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)

(7)传输状态查询

    FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)

    2019年9月21日星期六(STM32 spi接口flash)

注:SPI发送接收函数实现

u8 xxx(u8 data)

{

    //等待发送缓冲区为空

    while(SPI_I2S_GetFlagStatus(...)...);

    //发送数据

    SPI_I2S_SendData(.....);

    //同步接收 等待接收到数据

    while(SPI_I2S_GetFlagStatus(...)...);

    //接收数据

    return SPI_I2S_ReceiveData(...);

}

注:在和SPI从设备通信时先片选选中

    通信前片选拉低

通信完成片选拉高