- SPI介绍
SPI总线协议这部分网络上资料齐全,我这里就不多说了。在这里我主要介绍下,学习通信FLASH相关需要知道的地方。首先,需要准备以下资料:
- W25X16的数据手册;
- STM32F10x中文参考手册;
- STM32F10x固件库手册;
以上资料相关部分最好是看过的,主要是W25X16数据手册一定要看明白,STM32中文手册看一下SPI部分,在24章节开始。库函数打开Modules-STM32F10x_StdPeriph_Driver-SPI这里目录下。
对于SPI总线协议:
- 支持4种采集模式;
SPI模式 | CPOL | CPHA | 采样时刻 |
0 | 0 | 0 | 奇数边沿 |
1 | 0 | 1 | 偶数边沿 |
2 | 1 | 0 | 奇数边沿 |
3 | 1 | 1 | 偶数边沿 |
看完W25X16手册我们需要先知道:
- SPI的clk最大可达75Mhz;
- W25X16支持SPI模式0和模式3;
- W25X16传输数据是MSB先行
- W25X16内存分布:如下图1
图1 W25X16内存分布
如图1,对于W25x16来说,共有32个Block,每个Block为64KB,一共32*64=2048MB;每个Block又包含了16个Sector,每个Sector为4KB,16*4KB=64KB为一个Block。
我们看到不管是Block还是Sector 都有写了24字节的4个地址,从左到又都是00-FF刚好256Byte,所以显然通过内部芯片命令一次写入数据最大为256个字节。
看完STM32F10x中文参考手册和库文件手册我们需要大概知道:
- STM32的SPI总线支持CS为硬件NSS和普通IO,为了统一和方便设计,不管CS引脚接入到NSS还是其他普通IO上我们都以普通IO模式设计。
- STM32F1xx,SPI的时钟是最大为fPCLK/2,其中SPI1的FPCLK是72Mhz,其他SPI借口的Fpclk为36Mhz。
- STM32的SPI总线的CS引脚模式为:推挽输出;CLK和MOSI模式推挽复用输出;MISO模式为浮空输入或带上拉输入
- SPI支持传输8bit或者16bit数据一帧;可设置数据由MSB先行还是LSB先行。
- SPI初始化结构体都有哪些?库文件手册介绍了以下结构体
uint16_t | SPI_BaudRatePrescaler | 时钟分频系数 最大FCLK/2 |
uint16_t | SPI_CPHA | 配置相位模式,共计四中模式0~3模式。 |
uint16_t | SPI_CPOL | |
uint16_t | SPI_CRCPolynomial | CRC校验 |
uint16_t | SPI_DataSize | 一帧发数据8bit还是16bit |
uint16_t | SPI_Direction | 工作模式:单工、半双工、全双工 |
uint16_t | SPI_FirstBit | MSB还是LSB先行 |
uint16_t | SPI_Mode | 主还是从模式 |
uint16_t | SPI_NSS | 硬件CS还是软件CS |
每一个含义手册里说明的很清楚。
- 初始化代码
首先进行GPIO初始化:
void W25x16_SPI_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /*CS初始化*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /**CLK**/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //MISO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING GPIO_Init(GPIOA, &GPIO_InitStructure); //MOSI GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_4); //CS默认高电平 }
标准的初始化,GPIO的初始化比较简单, GPIO都在A PORT上。
然后对SPI工作模式初始化:
void W25x16_SPI_Workmode_Config(void) { SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //W25X16 FLASH 手册介绍 支持SPI 0和3 模式 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //选择模式3 CPOL=1 CPHA=1 偶数边沿 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //偶数边沿 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //设置CS为普通IO 还是硬件IO SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; // 1/2分频 SPI主频F/2 =72/2=36MHZ SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //发送数据 高位先行 SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1 , &SPI_InitStructure); SPI_Cmd(SPI1 , ENABLE); }
SPI工作模式的初始化,代码中注释写的很明白了,SPI_InitStructure.SPI_CRCPolynomial = 7; 这段初始化可有可无,因为我们不使用CRC。即便初始化了 后面也不会调用其对应函数来使用。
最后封装到新的函数中,放在Main函数中进行调用初始化即可
void W25x16_SPI_open(void) { W25x16_SPI_GPIO_Config(); W25x16_SPI_Workmode_Config() ; }
把这个函数调用以下就完成了SPI的初始化,今天就学习到这里,下一章我们学习,SPI基本发送读取函数和FLAHS基本函数。
原创文章,作者:小峰,如若转载,请注明出处:http://www.wfblog.com/archives/431.html