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:从设备使能
为了区分主设备和从设备的传输方向,我们通常以以下方式命名
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_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_FirstBit; /*!< 高地位顺序 SPI_FirstBit_MSB */ uint16_t
SPI_CRCPolynomial; /*!< CRC校验,不使用 */ |
(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从设备通信时先片选选中
通信前片选拉低
通信完成片选拉高