SPI全双工通信:全双工在时钟脉冲周期的每一个周期内,每当主设备同时发送一个字节的同时,会接受从设备接受一个字节数据,SPI全双工最大的特点就是发送和接受数据同步进行,发送多少数据就要接受多少数据。使用全双工通信的具体过程如下。
主设备发送数据(MOSI):主设备通过MOSI(Master Output Slaver Input )引脚发送数据。
从设备发送数据(MISO):从设备通过MISO(Master Input Slaver Output)引脚发送数据。
时钟同步(SCLK):主机发送多少个字节,就对应着要发送多少个时钟脉冲,每一个时钟脉冲对应着一个数据bit位。
片选信号(NSS/CS):拉低对应从机的片选信号,代表选中这个从机。
flash存储模块: W25Q64 后面的 64代表64Mbit 也就是 8MB 的总容量,划出64k容量称为块,每个块在划出4k的容量是扇区,在细分出256Byte是页。
这里对flash模块,写入数据的流程如下,首先要对模块写使能,然后对已经写过数据的区域进行写擦除,这里W25Q64闪存模块以及类似的模块中,写使能(Write Enbale)是一个必要的步奏,是为了防止各种意外写入。
hal(硬件抽象层)库中,需要将代码写到注释里面,这种写法在重新配置STM32CubleMX的时候,代码不会被删除,会保留注释区域内的代码。
W25Q64的数据手册里面,有写使能的地址,擦除命令格式,这里写使能是 0x06这个数据帧格式。
在函数结构体中,把这个地址,发送出去就完成了写使能,才能对W25Q64正常的写入数据,同样的擦除扇区也需要特定的数据帧命令,还有页编程地址,这些在数据手册里面都能找到,图放在下面,找到之后,在发送数据帧里面,加入就能完成对应的功能。
0x02擦除扇区,首地址,程序中将0x02,作为数据帧发送出去,就能完成对W25Q64的扇区擦除。
0x02页编程地址,数据帧首段有这个地址,就代表着,要对页4K 这个地址进行变成
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void SaveLEDSate(uint8_t ledstate)
{ //声明写使能数据帧
uint8_t Wtrite_EnableCmd[] = {0x06};
//写使能格式
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,Wtrite_EnableCmd,1,HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
//擦除扇区数据帧
uint8_t SecortErase[] = {0x20,0x00,0x00,0x00};
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,SecortErase,4,HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
HAL_Delay(100);
//在此写使能
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,Wtrite_EnableCmd,1,HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
//页编程
uint8_t pageProgCmd[5] = {0x02,0x00,0x00,0x00,ledstate};
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,pageProgCmd,5,HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
}
static uint8_t LoadLEDState(void)
{
uint8_t readDataCmd [] = {0x03,0x00,0x00,0x00};
uint8_t ledState = 0xff;
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,readDataCmd,4,HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi1,&ledState,1,HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
return ledState;
}
/* USER CODE END 0 */
/* USER CODE BEGIN PFP */
static void SaveLEDSate(uint8_t ledstate);
/* USER CODE END PFP */
到这里,就通过以上函数就能对W25Q64,进行写数据了。