- #include "user_config.h"
- #include "g32a1xxx_pins.h"
- #include "board.h"
- #include "w25q64.h"
- #include "bsp_spi.h"
- uint8_t write_array[5] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE};
- uint8_t read_array[5] = {0};
- uint8_t MID;
- uint16_t DID;
- int main(void)
- {
- /* Initialize clock */
- CLOCK_SYS_Init(&g_clockConfig);
-
- W25Q64_Init();
-
- W25Q64_ReadID(&MID, &DID);
-
- W25Q64_SectorErase(0x002000);//擦除指定扇区
- W25Q64_PageProgram(0x002000, write_array, 5);//在指定扇区写
- W25Q64_ReadData(0x002000, read_array, 5);//从指定扇区读
- while (1)
- {
- ;
- }
- }
软件SPI.c- #include "bsp_spi.h"
- //片选
- void MySPI_W_SS(uint8_t BitValue)
- {
- PINS_WritePin(CS_GPIO_BASE, CS_PIN, BitValue);
- }
- //时钟
- void MySPI_W_SCK(uint8_t BitValue)
- {
- PINS_WritePin(CLK_GPIO_BASE, CLK_PIN, BitValue);
- }
- //主机输出
- void MySPI_W_MOSI(uint8_t BitValue)
- {
- PINS_WritePin(MOSI_GPIO_BASE, MOSI_PIN, BitValue);
- }
- //从机输入
- uint8_t MySPI_R_MISO(void)
- {
- return (uint8_t)((PINS_ReadPinsInput(MISO_GPIO_BASE) >> MISO_PIN) & 0x01U);
- // return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
- }
- void BSP_SPI_Init(void)
- {
- /* Enable Clock to Port D */
- CLOCK_SYS_ConfigModuleClock(PMA_CLK, NULL);
- CLOCK_SYS_ConfigModuleClock(PMB_CLK, NULL);
- /* Set pin mode */
- PINS_SetMuxModeSel(CS_PORT_BASE, CS_PIN, PM_MUX_AS_GPIO);
- PINS_SetMuxModeSel(CLK_PORT_BASE, CLK_PIN, PM_MUX_AS_GPIO);
- PINS_SetMuxModeSel(MOSI_PORT_BASE, MOSI_PIN, PM_MUX_AS_GPIO);
- /* Set pin interrupt */
- PINS_SetPinIntSel(CS_PORT_BASE, CS_PIN, PM_DMA_INT_DISABLED);
- PINS_SetPinIntSel(CLK_PORT_BASE, CLK_PIN, PM_DMA_INT_DISABLED);
- PINS_SetPinIntSel(MOSI_PORT_BASE, MOSI_PIN, PM_DMA_INT_DISABLED);
- /* GPIO Initialization */
- PINS_SetPins(CS_GPIO_BASE, 1U << CS_PIN);
- PINS_SetPins(CLK_GPIO_BASE, 1U << CLK_PIN);
- PINS_SetPins(MOSI_GPIO_BASE, 1U << MOSI_PIN);
- /* Set pin as output */
- PINS_SetPinDir(CS_GPIO_BASE, CS_PIN, 1U);
- PINS_SetPinDir(CLK_GPIO_BASE, CLK_PIN, 1U);
- PINS_SetPinDir(MOSI_GPIO_BASE, MOSI_PIN, 1U);
-
- /* Set pin mode */
- PINS_SetMuxModeSel(MISO_PORT_BASE, MISO_PIN, PM_MUX_AS_GPIO);
- /* Set pin interrupt */
- PINS_SetPinIntSel(MISO_PORT_BASE, MISO_PIN, PM_DMA_INT_DISABLED);
- /* set pin input to enabled state */
- PINS_SetPmInputDisable(MISO_GPIO_BASE, 0U<<MISO_PIN);
- /* set pin Pull-up resistor */
- PINS_SetPullSel(MISO_PORT_BASE, MISO_PIN,PM_INTERNAL_PULL_UP_ENABLED);
-
- MySPI_W_SS(1);//高电平默认不选中从机
- MySPI_W_SCK(0);//模式0 空闲状态为低电平
- }
- void BSP_SPI_Start(void)
- {
- MySPI_W_SS(0);
- }
- void BSP_SPI_Stop(void)
- {
- MySPI_W_SS(1);
- }
- uint8_t BSP_SPI_SwapByte(uint8_t ByteSend)
- {
- uint8_t i,ByteReceive = 0x00;
-
- for (i = 0; i < 8; i++)
- {
- //使用掩码方式
- MySPI_W_MOSI(ByteSend & (0x80 >> i));//数据移出
- MySPI_W_SCK(1);//时钟变为高电平
- if (MySPI_R_MISO() == 1)
- {
- ByteReceive |= (0x80 >> i);//数据移入
- }
- MySPI_W_SCK(0);//时钟变为低电平
- }
-
- return ByteReceive;
- }
软件SPI.h
- #ifndef __BSP_SPI_H
- #define __BSP_SPI_H
- #include "g32a1xxx_pins.h"
- #include "user_config.h"
- //CS
- #define CS_PIN (0U)
- #define CS_PORT_BASE PMB
- #define CS_GPIO_BASE GPIOB
- //CLK
- #define CLK_PIN (1U)
- #define CLK_PORT_BASE PMB
- #define CLK_GPIO_BASE GPIOB
- //MOSI
- #define MOSI_PIN (0U)
- #define MOSI_PORT_BASE PMA
- #define MOSI_GPIO_BASE GPIOA
- //MISO
- #define MISO_PIN (1U)
- #define MISO_PORT_BASE PMA
- #define MISO_GPIO_BASE GPIOA
- void BSP_SPI_Init(void);
- void BSP_SPI_Start(void);
- void BSP_SPI_Stop(void);
- uint8_t BSP_SPI_SwapByte(uint8_t ByteSend);
- #endif
W25Q64.c
- #include "w25q64.h"
- #include "bsp_spi.h"
- void W25Q64_Init(void)
- {
- BSP_SPI_Init();
- }
- void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
- {
- BSP_SPI_Start();
- BSP_SPI_SwapByte(W25Q64_JEDEC_ID);
- *MID = BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE);
- *DID = BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE);
- *DID <<= 8;
- *DID |= BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE);
- BSP_SPI_Stop();
- }
- //写使能
- void W25Q64_WriteEnable(void)
- {
- BSP_SPI_Start();//片选
- BSP_SPI_SwapByte(W25Q64_WRITE_ENABLE);
- BSP_SPI_Stop();
- }
- //等待状态寄存器1 为非忙状态
- void W25Q64_WaitBusy(void)
- {
- uint32_t TimeOut;
- BSP_SPI_Start();//片选
- BSP_SPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);
- // while((BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01);
- TimeOut = 100000;
- while(BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01)
- {
- TimeOut--;
- if (TimeOut == 0)
- {
- break;
- }
- }
- BSP_SPI_Stop();
- }
- //开始写之前 先打开写使能,之后执行数据写入
- void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArry, uint16_t Count)
- {
- uint16_t i;
- W25Q64_WriteEnable();//写使能
-
- BSP_SPI_Start();//片选
- BSP_SPI_SwapByte(W25Q64_PAGE_PROGRAM);
- BSP_SPI_SwapByte(Address >> 16);
- BSP_SPI_SwapByte(Address >> 8);
- BSP_SPI_SwapByte(Address);
- for (i = 0; i < Count; i++)
- {
- BSP_SPI_SwapByte(DataArry[i]);
- }
- BSP_SPI_Stop();
-
- W25Q64_WaitBusy();//等待忙完
- }
- //擦除指定扇区 开启写使能 之后开始擦除扇区 最后等待状态寄存器为非忙状态
- void W25Q64_SectorErase(uint32_t Address)
- {
- W25Q64_WriteEnable();//写使能
-
- BSP_SPI_Start();//片选
- BSP_SPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);
- BSP_SPI_SwapByte(Address >> 16);
- BSP_SPI_SwapByte(Address >> 8);
- BSP_SPI_SwapByte(Address);
- BSP_SPI_Stop();
-
- W25Q64_WaitBusy();//等待忙完
- }
- //从指定地址读取数据
- void W25Q64_ReadData(uint32_t Address, uint8_t *DataArry, uint16_t Count)
- {
- uint16_t i;
- BSP_SPI_Start();//片选
- BSP_SPI_SwapByte(W25Q64_READ_DATA);
- BSP_SPI_SwapByte(Address >> 16);
- BSP_SPI_SwapByte(Address >> 8);
- BSP_SPI_SwapByte(Address);
- for (i = 0; i < Count; i++)
- {
- DataArry[i] = BSP_SPI_SwapByte(W25Q64_DUMMY_BYTE);
- }
- BSP_SPI_Stop();
- }
W25Q64.h- #ifndef __W25Q64_H
- #define __W25Q64_H
- #include "g32a1xxx_pins.h"
- #define W25Q64_WRITE_ENABLE 0x06
- #define W25Q64_WRITE_DISABLE 0x04
- #define W25Q64_READ_STATUS_REGISTER_1 0x05
- #define W25Q64_READ_STATUS_REGISTER_2 0x35
- #define W25Q64_WRITE_STATUS_REGISTER 0x01
- #define W25Q64_PAGE_PROGRAM 0x02
- #define W25Q64_QUAD_PAGE_PROGRAM 0x32
- #define W25Q64_BLOCK_ERASE_64KB 0xD8
- #define W25Q64_BLOCK_ERASE_32KB 0x52
- #define W25Q64_SECTOR_ERASE_4KB 0x20
- #define W25Q64_CHIP_ERASE 0xC7
- #define W25Q64_ERASE_SUSPEND 0x75
- #define W25Q64_ERASE_RESUME 0x7A
- #define W25Q64_POWER_DOWN 0xB9
- #define W25Q64_HIGH_PERFORMANCE_MODE 0xA3
- #define W25Q64_CONTINUOUS_READ_MODE_RESET 0xFF
- #define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID 0xAB
- #define W25Q64_MANUFACTURER_DEVICE_ID 0x90
- #define W25Q64_READ_UNIQUE_ID 0x4B
- #define W25Q64_JEDEC_ID 0x9F
- #define W25Q64_READ_DATA 0x03
- #define W25Q64_FAST_READ 0x0B
- #define W25Q64_FAST_READ_DUAL_OUTPUT 0x3B
- #define W25Q64_FAST_READ_DUAL_IO 0xBB
- #define W25Q64_FAST_READ_QUAD_OUTPUT 0x6B
- #define W25Q64_FAST_READ_QUAD_IO 0xEB
- #define W25Q64_OCTAL_WORD_READ_QUAD_IO 0xE3
- #define W25Q64_DUMMY_BYTE 0xFF
- void W25Q64_Init(void);//初始化函数
- void W25Q64_ReadID(uint8_t *MID, uint16_t *DID);//读取设备ID号
- void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArry, uint16_t Count);//在指定扇区写
- void W25Q64_SectorErase(uint32_t Address);//擦除指定扇区
- void W25Q64_ReadData(uint32_t Address, uint8_t *DataArry, uint16_t Count);//从指定扇区读
- #endif
实物展示:
效果展示: