硬件连接
本函数库来自正点原子官方,本人稍作修改和添加注释
W25Q16 2M Byte
W25Q256 32M Byte
spi 配置
2022-7-27 经过测试
- 华邦的 W25Q256JV 32M 字节 容量的spi flash没有问题 spi配置是 上升沿采集数据 —> CPOL =0 CPOA=0 或者是 CPOL=1 CPOA=1 hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
- 华邦的 W25Q16JVSSIQ 2M 字节 容量的spi flash没有问题
第1种配置
第2种配置
测试代码
- 需要修改CS片选引脚
- 需要选着spi外设
头文件
#ifndef __norflash_H
#define __norflash_H
#include "main.h"
#define SPI_SPEED_2 0
#define SPI_SPEED_4 1
#define SPI_SPEED_8 2
#define SPI_SPEED_16 3
#define SPI_SPEED_32 4
#define SPI_SPEED_64 5
#define SPI_SPEED_128 6
#define SPI_SPEED_256 7
#define NORFLASH_CS_GPIO_PORT GPIOA
#define NORFLASH_CS_GPIO_PIN GPIO_PIN_2
#define NORFLASH_CS_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
extern SPI_HandleTypeDef hspi1;
#define HSPI hspi1
#define NORFLASH_CS(x) do{ x ? \
HAL_GPIO_WritePin(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25Q256 0XEF18
#define BY25Q64 0X6816
#define BY25Q128 0X6817
#define NM25Q64 0X5216
#define NM25Q128 0X5217
extern uint16_t norflash_TYPE;
#define FLASH_WriteEnable 0x06
#define FLASH_WriteDisable 0x04
#define FLASH_ReadStatusReg1 0x05
#define FLASH_ReadStatusReg2 0x35
#define FLASH_ReadStatusReg3 0x15
#define FLASH_WriteStatusReg1 0x01
#define FLASH_WriteStatusReg2 0x31
#define FLASH_WriteStatusReg3 0x11
#define FLASH_ReadData 0x03
#define FLASH_FastReadData 0x0B
#define FLASH_FastReadDual 0x3B
#define FLASH_FastReadQuad 0xEB
#define FLASH_PageProgram 0x02
#define FLASH_PageProgramQuad 0x32
#define FLASH_BlockErase 0xD8
#define FLASH_SectorErase 0x20
#define FLASH_ChipErase 0xC7
#define FLASH_PowerDown 0xB9
#define FLASH_ReleasePowerDown 0xAB
#define FLASH_DeviceID 0xAB
#define FLASH_ManufactDeviceID 0x90
#define FLASH_JedecDeviceID 0x9F
#define FLASH_Enable4ByteAddr 0xB7
#define FLASH_Exit4ByteAddr 0xE9
#define FLASH_SetReadParam 0xC0
#define FLASH_EnterQPIMode 0x38
#define FLASH_ExitQPIMode 0xFF
static void norflash_wait_busy(void);
static void norflash_send_address(uint32_t address);
static void norflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
static void norflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
void norflash_init(void);
uint16_t norflash_read_id(void);
void norflash_write_enable(void);
uint8_t norflash_read_sr(uint8_t regno);
void norflash_write_sr(uint8_t regno,uint8_t sr);
void norflash_erase_chip(void);
void norflash_erase_sector(uint32_t saddr);
void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
#endif
源文件
- 需要移植 spi读写函数
uint8_t spi2_read_write_byte(uint8_t send_data)
- 需要移植spi速度修改函数—也可以不修改–非必要
void spi2_set_speed(uint8_t speed)
spi flash操作库源文件
#include "norflash.h"
#include "stdio.h"
uint16_t g_norflash_type = NM25Q128;
uint8_t spi2_read_write_byte(uint8_t send_data)
{
uint8_t recv_data;
HAL_SPI_TransmitReceive(&HSPI, &send_data, &recv_data, 1, 0xffff);
return recv_data;
}
void spi2_set_speed(uint8_t speed)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(speed));
__HAL_SPI_DISABLE(&HSPI);
HSPI.Instance->CR1 &= 0xFFC7;
HSPI.Instance->CR1 |= speed << 3;
__HAL_SPI_ENABLE(&HSPI);
}
void norflash_init(void)
{
spi2_set_speed(SPI_SPEED_4);
uint8_t temp=0;
g_norflash_type = norflash_read_id();
if (g_norflash_type == W25Q256)
{
temp = norflash_read_sr(3);
if ((temp & 0x01) == 0)
{
norflash_write_enable();
temp |= 1 << 1;
norflash_write_sr(3, temp);
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_Enable4ByteAddr);
NORFLASH_CS(1);
}
}
}
static void norflash_wait_busy(void)
{
while ((norflash_read_sr(1) & 0x01) == 0x01);
}
void norflash_write_enable(void)
{
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_WriteEnable);
NORFLASH_CS(1);
}
static void norflash_send_address(uint32_t address)
{
if (g_norflash_type == W25Q256)
{
spi2_read_write_byte((uint8_t)((address) >> 24));
}
spi2_read_write_byte((uint8_t)((address) >> 16));
spi2_read_write_byte((uint8_t)((address) >> 8));
spi2_read_write_byte((uint8_t)address);
}
uint8_t norflash_read_sr(uint8_t regno)
{
uint8_t byte = 0, command = 0;
switch (regno)
{
case 1:
command = FLASH_ReadStatusReg1;
break;
case 2:
command = FLASH_ReadStatusReg2;
break;
case 3:
command = FLASH_ReadStatusReg3;
break;
default:
command = FLASH_ReadStatusReg1;
break;
}
NORFLASH_CS(0);
spi2_read_write_byte(command);
byte = spi2_read_write_byte(0xFF);
NORFLASH_CS(1);
return byte;
}
void norflash_write_sr(uint8_t regno, uint8_t sr)
{
uint8_t command = 0;
switch (regno)
{
case 1:
command = FLASH_WriteStatusReg1;
break;
case 2:
command = FLASH_WriteStatusReg2;
break;
case 3:
command = FLASH_WriteStatusReg3;
break;
default:
command = FLASH_WriteStatusReg1;
break;
}
NORFLASH_CS(0);
spi2_read_write_byte(command);
spi2_read_write_byte(sr);
NORFLASH_CS(1);
}
uint16_t norflash_read_id(void)
{
uint16_t deviceid;
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_ManufactDeviceID);
spi2_read_write_byte(0);
spi2_read_write_byte(0);
spi2_read_write_byte(0);
deviceid = spi2_read_write_byte(0xFF) << 8;
deviceid |= spi2_read_write_byte(0xFF);
NORFLASH_CS(1);
return deviceid;
}
void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
uint16_t i;
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_ReadData);
norflash_send_address(addr);
for (i = 0; i < datalen; i++)
{
pbuf[i] = spi2_read_write_byte(0xFF);
}
NORFLASH_CS(1);
}
static void norflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
uint16_t i;
norflash_write_enable();
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_PageProgram);
norflash_send_address(addr);
for (i = 0; i < datalen; i++)
{
spi2_read_write_byte(pbuf[i]);
}
NORFLASH_CS(1);
norflash_wait_busy();
}
static void norflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
uint16_t pageremain;
pageremain = 256 - addr % 256;
if (datalen <= pageremain)
{
pageremain = datalen;
}
while (1)
{
norflash_write_page(pbuf, addr, pageremain);
if (datalen == pageremain)
{
break;
}
else
{
pbuf += pageremain;
addr += pageremain;
datalen -= pageremain;
if (datalen > 256)
{
pageremain = 256;
}
else
{
pageremain = datalen;
}
}
}
}
uint8_t g_norflash_buf[4096];
void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t *norflash_buf;
norflash_buf = g_norflash_buf;
secpos = addr / 4096;
secoff = addr % 4096;
secremain = 4096 - secoff;
if (datalen <= secremain)
{
secremain = datalen;
}
while (1)
{
norflash_read(norflash_buf, secpos * 4096, 4096);
for (i = 0; i < secremain; i++)
{
if (norflash_buf[secoff + i] != 0XFF)
{
break;
}
}
if (i < secremain)
{
norflash_erase_sector(secpos);
for (i = 0; i < secremain; i++)
{
norflash_buf[i + secoff] = pbuf[i];
}
norflash_write_nocheck(norflash_buf, secpos * 4096, 4096);
}
else
{
norflash_write_nocheck(pbuf, addr, secremain);
}
if (datalen == secremain)
{
break;
}
else
{
secpos++;
secoff = 0;
pbuf += secremain;
addr += secremain;
datalen -= secremain;
if (datalen > 4096)
{
secremain = 4096;
}
else
{
secremain = datalen;
}
}
}
}
void norflash_erase_chip(void)
{
norflash_write_enable();
norflash_wait_busy();
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_ChipErase);
NORFLASH_CS(1);
norflash_wait_busy();
}
void norflash_erase_sector(uint32_t saddr)
{
saddr *= 4096;
norflash_write_enable();
norflash_wait_busy();
NORFLASH_CS(0);
spi2_read_write_byte(FLASH_SectorErase);
norflash_send_address(saddr);
NORFLASH_CS(1);
norflash_wait_busy();
}
测试使用函数
重定向printf函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 0xffff);
return ch;
}
spi flash 测试函数
void spi_flash_test()
{
int x = 0;
norflash_init();
uint8_t buf[256];
for(x = 0; x < 256; x++)buf[x] = x;
norflash_write(buf, 0, 256);
memset(buf, 0, 256);
norflash_read(buf, 0, 256);
for(x = 0; x < 256; x++)
{
if(buf[x] != x)break;
}
if(x != 256)
{
printf("spi flash test fail\r\n");
}
else
{
printf("spi flash test ok\r\n");
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)