SPI怎么配置:
控制器配置(更稳定效率高)
IO模拟的方式(更灵活移植性高)
首先我会选择用IO模拟的方式配置,SPI根据时钟极性以及时钟相位的不同对应不同等的时序,我选择用时钟极性和时钟相位都为0状态的通信时序,根据时序找到通信规则。然后写两个函数,一个是IO控制器配置函数,一个是数据接收发送一体函数。以上就是SPI通信配置。
W25Q64存储结构:一共64M位,8M字节,一页256字节,16页为一个扇区,16个扇区为1块。共有2048个扇区,128块。
W25Q64引脚介绍
CS:低电平选中芯片开始通信-------------------PB14
wp:写保护 低电平开启写保护
HOLD:低电平时其他引脚断开,高电平时,正常工作
SCLK:-------------------------PA5
DO ;-----------MISO-------PA6
DI :-----------MOSI-------PA7
内部地址表示方式:0X某块(占两位)某扇区(占一位)某页(占一位)某字节 eg:0x12 3 4 56 转成10进制 --------18块的第3个扇区的第4页的86个字节
存储原理:不拆擦除前只能写0不能写1,擦除后的空间都是1
如何使用W25Q64的:
1.首先根据查看它的说明手册发现它是支持标准的SPI接口,可以用SPI通信
2.根据原理图我能知道他用到主控芯片的哪些IO
3.根据器件手册设计的程序 移植SPI底层协议的程序 再根据我们的需求写一些相关的读写擦除等函数
总结:存储结构 引脚 如何配置从器件的寄存器(通过发送指令控制W25Q64内部寄存器) 程序设计 存储结构体变量
如果W25Q64里某个扇区存储了不同的数据类型,现在要改变某个参数,有什么办法在改变参数的同时不影响同扇区其他内容?
方法1:
1.定义一个结构体变量,读这个扇区的数据,将数据放在结构体变量里
2.擦除扇区
3.将要改变的参数设置成员改变参数
4.再将结构体写入扇区
方法2:
定义一个大数组如下图:
/***********SPI控制器配置通信方式**********/
/**************
*函数名 :spi1_init
*函数功能 :SPI通信IO初始化
*函数参数 :void
*函数返回值:void
*函数描述 :SCL---时钟线 --- 复用输出---PA5
MOSI--主出从入---复用输出---PA7
MISO--主入从出---复用输入---PA6
**************/
void spi1_init(void)
{
/*IO控制器配置*/
//IO时钟使能
RCC->AHB1ENR |= (1<<0);
//模式配置
GPIOA->MODER &=~ (0x3f<<10);
GPIOA->MODER |= (0x2a<<10);//PA5 PA6 PA7复用模式
//输出类型配置
GPIOA->OTYPER &=~ (5<<5); //PA5 PA7推挽输出
//
//输出速度配置
GPIOA->OSPEEDR &=~ (0x33<<10);//PA5 PA7 50Mhz速度
GPIOA->OSPEEDR |= (0x22<<10);//PA5 PA7 50Mhz速度
//复用模式配置
GPIOA->AFR[0] &= ~(0xfff<<20);
GPIOA->AFR[0] |= (0x555<<20);// SPI---AF5
/***SPI控制器配置***/
RCC->APB2ENR |= (1<<12);//spi时钟使能
SPI1->CR1 &=~(1<<15);//双线单向通信
SPI1->CR1 &=~(1<<11);//8位数据帧
SPI1->CR1 &=~(1<<10);//全双工
SPI1->CR1 |= (3<<8);//软件从器件管理允许通信
SPI1->CR1 &=~(1<<7);//先发送高位
SPI1->CR1 &=~(7<<3);//波特率 2分频
SPI1->CR1 |= (1<<2);//配置为主模式
SPI1->CR1 &=~(1<<1);//时钟极性为0
SPI1->CR1 &=~(1<<0);//时钟相位为0
SPI1->CR1 |= (1<<6);//使能
}
/**************
*函数名 :spi1_byte
*函数功能 :SPI通信数据交换(控制器配置的方式)
*函数参数 :u8 data
*函数返回值:u8
*函数描述 :SCL---时钟线---PA5
MOSI--主出从入 通用推挽输出模式---PA7
MISO--主入从出 通用输入模式---PA6
**************/
u8 spi1_byte(u8 data)
{
u8 val;
//等待发送缓冲区为空
while(!(SPI1->SR & (1<<1)));
//将数据给到SPI_DR寄存器
SPI1->DR=data;
//等待接收缓冲区为空
while(!(SPI1->SR & (1<<0)));
//读SPI_DR寄存器里的值
val=SPI1->DR;
return val;
}