目录
对SPI进行结构封装,方便使用。方便讲解,用W25Q64芯片进行讲解
#define SPI_CS_PROT GPIOB //CS接线引脚通道,
#define SPI_CS_PIN GPIO_Pin_11
#define SPI_DO_PROT GPIOB //D0接线引脚通道,
#define SPI_DO_PIN GPIO_Pin_10
#define SPI_SLK_PROT GPIOB //CL接线引脚通道,
#define SPI_SLK_PIN GPIO_Pin_0
#define SPI_DI_PROT GPIOB //DI接线引脚通道,
#define SPI_DI_PIN GPIO_Pin_1
#define MYSPI_W_CS(x) GPIO_WriteBit(SPI_CS_PROT,SPI_CS_PIN,(BitAction)(x))//对CS线进行操作
#define MYSPI_W_DI(x) GPIO_WriteBit(SPI_DI_PROT,SPI_DI_PIN,(BitAction)(x))//对DI线进行操作
#define MYSPI_W_SLK(x) GPIO_WriteBit(SPI_SLK_PROT,SPI_SLK_PIN,(BitAction)(x))//对SLK线进行操作
void MySPI_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SPI_CS_PIN|SPI_SLK_PIN|SPI_DI_PIN;
GPIO_Init(SPI_CS_PROT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //DO输入引脚为上拉输入,其他均为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SPI_DO_PIN;
GPIO_Init(SPI_CS_PROT, &GPIO_InitStructure);
MYSPI_W_CS(1);
MYSPI_W_SLK(0);
}
注意:
在最后对CS拉高,SLK拉低。
1.开始和结束代码
如图进行开始结束代码封装:
void MySPI_Start(void)
{
MYSPI_W_CS(0); //拉低为开始信号
}
void MySPI_Stop(void)
{
MYSPI_W_CS(1); //拉高为结束信号
}
2.交换字节操作
uint8_t MySPI_SwapByte(uint8_t ByteSend) //
{
uint8_t i;
for(i = 0;i < 8;i ++)
{
MYSPI_W_DI(ByteSend & 0x80 ); //
ByteSend <<= 1;
MYSPI_W_SLK(1);
if(MySPI_Read_MISO() == 1){ByteSend |= 0x01;} //接受值为从机发送值
MYSPI_W_SLK(0);
}
return ByteSend;
}
注意:
ByteSend值在最后已经改变为输入的值,切记在此时值已经改变?
1.在此对W25Q64芯片进行ID读取
读取函数:
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID)
{
MySPI_Start();
MySPI_SwapByte(0x9F); //进行读取ID命令
*MID = MySPI_SwapByte(0xFF); //将厂商ID 进行读取赋值
*DID = MySPI_SwapByte(0xFF);
*DID <<= 8;
*DID |= MySPI_SwapByte(0xFF);
MySPI_Stop();
}
显示函数:
uint8_t MID;
uint16_t DID;
int main(void)
{
OLED_Init();
W25Q64_Init();
W25Q64_ReadID(&MID,&DID);
OLED_ShowHexNum(1, 1, MID, 2);
OLED_ShowHexNum(3, 1, DID, 4);
}
在此对SPI的时序进行了简单的介绍