2019年9月21日星期六(STM32)

一.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:从设备使能

 

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

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

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

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

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

2.通信原理

 

 

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

3.时钟的相位和极性

(1)时钟极性

    决定时钟线的默认电平

    CPOL = 1 默认高电平

    CPOL = 0 默认低电平

(2)时钟相位

    决定第几个边沿读写

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

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

 

 

4.stm32f407的SPI控制器

 

 

 

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

1.原理图

 

 

 2.w25q128的说明手册

(1)高地位顺序和极性

    MSB

    mode = 0(默认低电平)

    mode = 1(默认高电平)

    

    上升沿input 下降沿output

(2)状态寄存器1和2

 

 

(3)芯片操作

 

   

 

 

 

 

 

 

 

 

 

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)

    

注:SPI发送接收函数实现

u8 xxx(u8 data)

{

    //等待发送缓冲区为空

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

    //发送数据

    SPI_I2S_SendData(.....);

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

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

    //接收数据

    return SPI_I2S_ReceiveData(...);

}

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

    通信前片选拉低

通信完成片选拉高

猜你喜欢

转载自www.cnblogs.com/zjlbk/p/11573985.html
今日推荐