STM32-CubuMX-HAL库学习(八)-- SPI通信写入和读取W25Q64

硬件平台:正点原子STM32MINI开发板(STM32RCT6)
软件平台:STM32CubeMX
KEIL5
实现功能:用硬件SPI1读取板载W25Q64
硬件连接: PA5->SPI_CLK
PA6->SPI_MISO
PA7->SPI_MOSI
PA2->SPI_NSS
说明:有时候程序下载后不实现,可试着复位一下,也可在魔术棒配置中打开下载后复位。
(仅仅写了SPI配置部分,其余初始化以及工程配置未做说明)
参考博客:
https://blog.csdn.net/weixin_41294615/article/details/103233374?ops_request_misc=&request_id=&biz_id=102&utm_term=HAL%25E5%25BA%2593%25E5%25AE%259E%25E7%258E%25B0SPI%25E9%2580%259A%25E4%25BF%25A1%25E6%2593%258D%25E4%25BD%259CW25Q64&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-103233374.first_rank_v2_pc_rank_v29
在这里插入图片描述
1、打开SPI1,选择全双工模式,MSB先行,时钟分频任意,只要不超过18M即可,选择软件触发
在这里插入图片描述
2、初始化PA2,当做SPI软件触发引脚,然后配置好工程其他文件生成代码即可。
以下为测试代码,有参考上面链接的博客,也有一些修改,可以放在main.c中进行测试

#define SPI_NSS_HIGH();  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET);
#define SPI_NSS_LOW();   HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET);
#define MY_HSPI          hspi1

/* W25Q64的指令 */
uint8_t w25x_read_id = 0x90;					// 读ID
uint8_t m_addr[3]    = {0,0,0};					// 测试地址0x000000
uint8_t check_addr   = 0x05;					// 检查线路是否繁忙
uint8_t enable_write = 0x06;					// 使能了才能改变芯片数据
uint8_t erase_addr   = 0x20;					// 擦除命令
uint8_t write_addr   = 0x02;					// 写数据命令
uint8_t read_addr    = 0x03;					// 读数据命令

uint8_t temp_ID[5] = {0,0,0,0,0};						// 接收缓存
uint8_t temp_wdata[5] = {0x99,0x88,0x77,0x66,0x55};		// 需要写入的数据
uint8_t temp_rdata[5] = {0,0,0,0,0};					// 读出数据保存的buff
/* 读ID */
void ReadID(void)
{
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &w25x_read_id, 1, 100);		// 读ID发送指令
	HAL_SPI_Receive(&MY_HSPI, temp_ID, 5, 100);				// 读取ID
	SPI_NSS_HIGH();	                                        // 失能CS
}

/* 检查是否繁忙 */
void CheckBusy(void)
{
	uint8_t status=1;
	uint32_t timeCount=0;
	do
	{
		timeCount++;
		if(timeCount > 0xEFFFFFFF) //等待超时
		{
			return ;
		}
		
		SPI_NSS_LOW();	                                            // 使能CS	
		HAL_SPI_Transmit(&MY_HSPI, &check_addr, 1, 100);			// 发送指令
		HAL_SPI_Receive(&MY_HSPI, &status, 1, 100);				    // 读取
		SPI_NSS_HIGH();                                             // 失能CS
	}while((status&0x01)==0x01);
}


/* 写入数据 */
void WriteData(void)
{
	/* 检查是否繁忙 */
	CheckBusy();
	
	/* 写使能 */
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &enable_write, 1, 100);		// 发送指令
	SPI_NSS_HIGH(); 	                                    // 失能CS
	
	/* 擦除 */
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &erase_addr, 1, 100);		// 发送指令
	HAL_SPI_Transmit(&MY_HSPI, m_addr, 3, 100);				// 发送地址
	SPI_NSS_HIGH(); 	                                    // 失能CS
	
	/* 再次检查是否繁忙 */
	CheckBusy();
	
	/* 写使能 */
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &enable_write, 1, 100);		// 发送指令
	SPI_NSS_HIGH(); 	                                    // 失能CS

	/* 写数据 */
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &write_addr, 1, 100);		// 发送指令
	HAL_SPI_Transmit(&MY_HSPI, m_addr, 3, 100);				// 地址
	HAL_SPI_Transmit(&MY_HSPI, temp_wdata, 5, 100);			// 写入数据
	SPI_NSS_HIGH(); 	                                    // 失能CS
}

/* 读取数据 */
void ReadData(void)
{
	/* 检查是否繁忙 */
	CheckBusy();	
	
	/* 开始读数据 */
	SPI_NSS_LOW();	                                        // 使能CS
	HAL_SPI_Transmit(&MY_HSPI, &read_addr, 1, 100);			// 读发送指令
	HAL_SPI_Transmit(&MY_HSPI, m_addr, 3, 100);				// 地址
	HAL_SPI_Receive(&MY_HSPI,  temp_rdata, 5, 100);			// 拿到数据
	SPI_NSS_HIGH(); 	                                    // 失能CS
}


main函数中初始化后分别执行以下代码
ReadID();
WriteData();
ReadData();
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是使用STM32F4 HAL进行SPI读写W25Q32的示例代码: ```c #include "stm32f4xx_hal.h" #include <string.h> /* 定义SPI接口 */ SPI_HandleTypeDef hspi1; /* 定义W25Q32的命令码 */ #define W25Q32_CMD_WRITE_ENABLE 0x06 #define W25Q32_CMD_WRITE_DISABLE 0x04 #define W25Q32_CMD_READ_STATUS_REG1 0x05 #define W25Q32_CMD_READ_STATUS_REG2 0x35 #define W25Q32_CMD_READ_DATA 0x03 #define W25Q32_CMD_PAGE_PROGRAM 0x02 #define W25Q32_CMD_ERASE_SECTOR 0x20 #define W25Q32_CMD_ERASE_CHIP 0xC7 /* 定义W25Q32的状态寄存器 */ typedef struct { uint8_t busy:1; uint8_t write_enable_latch:1; uint8_t block_protection:3; uint8_t reserved:1; uint8_t page_size:2; } w25q32_status_reg1_t; /* 初始化SPI接口 */ void MX_SPI1_Init(void) { /* SPI1 parameter configuration */ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } /* 读取W25Q32的状态寄存器1 */ void w25q32_read_status_reg1(w25q32_status_reg1_t *status_reg) { uint8_t cmd = W25Q32_CMD_READ_STATUS_REG1; uint8_t data[2]; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Receive(&hspi1, data, sizeof(data), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); status_reg->busy = (data[0] & 0x01); status_reg->write_enable_latch = ((data[0] >> 1) & 0x01); status_reg->block_protection = ((data[0] >> 2) & 0x07); status_reg->reserved = ((data[0] >> 5) & 0x01); status_reg->page_size = ((data[1] >> 6) & 0x03); } /* 写入W25Q32的状态寄存器1 */ void w25q32_write_status_reg1(w25q32_status_reg1_t *status_reg) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_PAGE_PROGRAM; uint8_t data[2] = {0}; data[0] |= (status_reg->busy & 0x01); data[0] |= (status_reg->write_enable_latch & 0x01) << 1; data[0] |= (status_reg->block_protection & 0x07) << 2; data[0] |= (status_reg->reserved & 0x01) << 5; data[1] |= (status_reg->page_size & 0x03) << 6; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, data, sizeof(data), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 写入W25Q32的一页数据 */ void w25q32_write_page(uint32_t addr, uint8_t *data, uint32_t len) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_PAGE_PROGRAM; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 读取W25Q32的一页数据 */ void w25q32_read_page(uint32_t addr, uint8_t *data, uint32_t len) { uint8_t cmd = W25Q32_CMD_READ_DATA; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_SPI_Receive(&hspi1, data, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 擦除W25Q32的一个扇区 */ void w25q32_erase_sector(uint32_t addr) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_ERASE_SECTOR; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 擦除W25Q32的整个芯片 */ void w25q32_erase_chip(void) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_ERASE_CHIP; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } int main(void) { /* 初始化HAL */ HAL_Init(); /* 初始化SPI接口 */ MX_SPI1_Init(); /* 定义状态寄存器并读取 */ w25q32_status_reg1_t status_reg; w25q32_read_status_reg1(&status_reg); /* 写入一页数据 */ uint8_t data[256]; memset(data, 0xFF, sizeof(data)); w25q32_write_page(0x000000, data, sizeof(data)); /* 读取一页数据 */ uint8_t read_data[256]; w25q32_read_page(0x000000, read_data, sizeof(read_data)); /* 擦除一个扇区 */ w25q32_erase_sector(0x000000); /* 擦除整个芯片 */ w25q32_erase_chip(); while (1) { } } ``` 需要注意的是,上述代码中的W25Q32的命令码和状态寄存器的定义仅适用于W25Q32型号的Flash芯片,如果需要使用其他型号的Flash芯片,需要根据数据手册自行修改。同时,还需要根据实际硬件连接情况修改SPI接口的初始化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年、潜行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值