注意的点:1.片选信号CS的使用。2.采集数据的位数,采集的16位数据用8位数据存放,导致一直得不到正确的结果。
1.SPI根据电平空闲时的状态,以及读取第一个数据是在什么时候,一共有4种模式。(具体可以在站内查询,非常详细)
2.和之前的情况一样,SPI通信依靠时钟的上下沿来对数据进行发送和读取,所以我们可以在一个周期内把对一个bit位数据的发送和读取同时完成。
3.我们的单片机是35MHz的,而GD25Q54芯片的spi通信速率最大可以是120MHz,所以我们在写这个函数的时候,可以直接修改引脚电平,不用做时延。
#include "gd25q64.h"
#include "stc8g.h"
sbit CS = P5^4;
sbit MOSI = P4^0;
sbit MISO = P4^1;
sbit SCLK = P4^3;
// 4.在时钟上升沿发送,下降沿接收。
unsigned char SPI_RW(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
SCLK = 0; //这里先构造时钟源低电平
MOSI = (dat&0x80); //把数据准备好
SCLK = 1; //把时钟拉高,出现上升沿,数据发送出去
dat <<= 1; //左移一位,因为SPI通信是从最高位开始发送的
SCLK = 0; //拉低时钟,出现下降沿
dat |= MISO; //把接收的数据放到,dat的最低位,dat左移后最低位补0,
// 所以不会有影响 。循环8次后,数据收发完成
}
return dat;
}
//5. 这里写读取芯片ID的函数。芯片手册上说发送0x90后再发送3次0x00,就可以接收到芯片ID
找bug找的头都要大了,第一个问题,写函数的时候忘记 CS = 0; 这个操作是片选操作,拉低后就表示使用这个芯片。数据收发完成后 CS = 1; 结束通信。
最恶心的地方是读取的芯片ID是16位的 ,需要用 int变量来存放
unsigned int temp ,temp1 ,temp2; //刚开始这里定义的是char 变量,读取的结果总是00 00,坑死
6.这个芯片读取数据的时候,需要按一下复位键,串口才会报ID。这个函数可以专门读取数据,这个时候,输入的值对结果不影响,所以就随便写为0x00了
unsigned int ReadID(void)
{
unsigned int temp ,temp1 ,temp2;
CS = 0;
SPI_RW(0x90);
SPI_RW(0x00);
SPI_RW(0x00);
SPI_RW(0x00);
temp1 = SPI_RW(0x00);
temp2 = SPI_RW(0x00);
CS = 1;
temp = (temp1 <<8) + temp2;
return temp;
}