赞
踩
目录
四、软件SPI读写STM32F103ZET6板载W25Q16的ID号
SPI的英文全称为Serial Peripheral Interface,是一种通用数据总线。较为重要的端口为MOSI(主机输出,从机输入)、MISO(主机输入,从机输出)、SCL(总线时钟)、CS(片选信号)。
如下图所示,主机的MOSI与从机的SDI(Slave Data Input)相连,主机的MISO与从机的SDO(Slave Data Output),主机片选信号CS与从机片选相连(Chip Select)通常低电平有效,时钟总线相连一起。根据输入输出特性,在软件SPI中,将MOSI、SCL、CS配置为推挽输出、将MISO配置成上拉输入即可。
SPI主机与从机通讯实际上时两者的移位寄存器交换数据的过程,在时钟信号SCL的推动下,主机发送一位,从机也发送一位,两者互换数据,交换8次之后,便完成了一个字节的传输。
代码前提:
- void MySPI_W_CS(uint8_t value)
- {
- GPIO_WriteBit(SPI_PORT,SPI_CS_PIN,(BitAction)value);
- }
- void MySPI_W_SCL(uint8_t value)
- {
- GPIO_WriteBit(SPI_PORT,SPI_SCL_PIN,(BitAction)value);
- }
- void MySPI_W_MOSI(uint8_t value)
- {
- GPIO_WriteBit(SPI_PORT,SPI_MOSI_PIN,(BitAction)value);
- }
- uint8_t MySPI_R_MISO(void )
- {
- return GPIO_ReadInputDataBit(SPI_PORT,SPI_MISO_PIN);;
- }

片选信号由高至低,即选中从机芯片通讯的过程。
- void MySPI_Start(void )
- {
- MySPI_W_CS(0);
- }
片选信号由低至高,即不选从机芯片的过程。
- void MySPI_Stop(void )
- {
- MySPI_W_CS(1);
- }
介绍一种最常用的通讯模式:CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。
- uint8_t MySPI_SwapData(uint8_t Data)
- {
- uint8_t temp=0x00;
- for (int i = 0; i < 8; i++)
- {
- MySPI_W_MOSI(Data & (0x80>>i));
- MySPI_W_SCL(1);
- if(MySPI_R_MISO()==1)
- {
- temp|=(0x80>>i);
- }
- MySPI_W_SCL(0);
- }
- return temp;
- }
多数商家所售STM32F103ZET6自带一块支持SPI通讯的W25Q16,如下图:
原理图如下:观察可知,所接的PB12、13、14、15也为板上ZET6班上对应的硬件SPI资源,本文中我们使用软件时序模拟SPI。
本文中我们读出该设备ID号 :查看手册可知:MID为EF(十六进制),DID为4015(十六进制)。
- void MySPI_Init(void )
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin=SPI_CS_PIN|SPI_SCL_PIN|SPI_MOSI_PIN;
- GPIO_Init(SPI_PORT,&GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Pin=SPI_MISO_PIN;
- GPIO_Init(SPI_PORT,&GPIO_InitStructure);
-
- MySPI_W_CS(1);
- MySPI_W_SCL(0);
- }

- void W25Q16_Init(void )
- {
- MySPI_Init();
- }
- void W25Q16_Read_ID(uint8_t* MID,uint16_t* DID)
- {
- MySPI_Start();
- MySPI_SwapData(0x9F);
- *MID=MySPI_SwapData(0xFF);
- *DID=MySPI_SwapData(0xFF);
- *DID<<=8;
- *DID|=MySPI_SwapData(0xFF);
- MySPI_Stop();
- }
- #include "main.h"
- static int i=0;
- int main(void)
- {
- uint8_t MID=0;
- uint16_t DID=0;
- uart_init(115200);
- delay_init();
- OLED_Init();
- OLED_Clear();
- W25Q16_Init();
- W25Q16_Read_ID(&MID,&DID);
- while(1)
- {
- for (; i < 1; ++i) {
- OLED_Init();
- OLED_Clear();
- }
- OLED_ShowString(1,0,"MID:",16);
- OLED_ShowString(1,2,"DID:",16);
- OLED_ShowHexNum(40,0,MID,2);
- OLED_ShowHexNum(40,2,DID,4);
- }
- return 0;
- }

符合最终的现象,正确读出设备ID号!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。