赞
踩
输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入
包装四个SPI通信引脚
在初始化函数里,SS默认高电平,SCK默认是低电平
接下来开始写SPI的三个时序基本单元
开始函数
停止函数
交换一个字节
调用MySPI
参考手册指令集部分
比如要获取读ID号的指令
起始
先交换发送指令9F,随后连续交换接收三个字节(在括号“()”中的字节字段表示从设备上的DO引脚读取的数据。)
停止
规定
编写等待忙函数
读取状态寄存器1的最后一位
判断是不是1,等待忙
编写页编程
MySPI.c
#include "stm32f10x.h" // Device header void MySPI_W_SS(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue); } void MySPI_W_SCK(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue); } void MySPI_W_MOSI(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue); } uint8_t MySPI_R_MISO(void) { return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); } void MySPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); MySPI_W_SS(1); MySPI_W_SCK(0); } void MySPI_Start(void) { MySPI_W_SS(0); } void MySPI_Stop(void) { MySPI_W_SS(1); } uint8_t MySPI_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; }
MySPI.h
#ifndef __MYSPI_H
#define __MYSPI_H
void MySPI_Init(void);
void MySPI_Start(void);
void MySPI_Stop(void);
uint8_t MySPI_SwapByte(uint8_t ByteSend);
#endif
W25Q64.c
#include "stm32f10x.h" // Device header #include "MySPI.h" #include "W25Q64_Ins.h" void W25Q64_Init(void) { MySPI_Init(); } void W25Q64_ReadID(uint8_t *MID, uint16_t *DID) { MySPI_Start(); MySPI_SwapByte(W25Q64_JEDEC_ID); *MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE); *DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE); *DID <<= 8; *DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE); MySPI_Stop(); } void W25Q64_WriteEnable(void) { MySPI_Start(); MySPI_SwapByte(W25Q64_WRITE_ENABLE); MySPI_Stop(); } void W25Q64_WaitBusy(void) { uint32_t Timeout; MySPI_Start(); MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1); Timeout = 100000; while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01) { Timeout --; if (Timeout == 0) { break; } } MySPI_Stop(); } void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count) { uint16_t i; W25Q64_WriteEnable(); MySPI_Start(); MySPI_SwapByte(W25Q64_PAGE_PROGRAM); MySPI_SwapByte(Address >> 16); MySPI_SwapByte(Address >> 8); MySPI_SwapByte(Address); for (i = 0; i < Count; i ++) { MySPI_SwapByte(DataArray[i]); } MySPI_Stop(); W25Q64_WaitBusy(); } void W25Q64_SectorErase(uint32_t Address) { W25Q64_WriteEnable(); MySPI_Start(); MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB); MySPI_SwapByte(Address >> 16); MySPI_SwapByte(Address >> 8); MySPI_SwapByte(Address); MySPI_Stop(); W25Q64_WaitBusy(); } void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) { uint32_t i; MySPI_Start(); MySPI_SwapByte(W25Q64_READ_DATA); MySPI_SwapByte(Address >> 16); MySPI_SwapByte(Address >> 8); MySPI_SwapByte(Address); for (i = 0; i < Count; i ++) { DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE); } MySPI_Stop(); } //void W25Q64_WriteStatus(void) //{ // W25Q64_WriteEnable(); //写使能 // // MySPI_Start(); // MySPI_SwapByte(W25Q64_WRITE_STATUS_REGISTER); //发送写状态寄存器的指令 // MySPI_SwapByte(0x00); //写入状态寄存器1 // MySPI_SwapByte(0x00); //写入状态寄存器2 // MySPI_Stop(); // // W25Q64_WaitBusy(); //等待忙 //}
W25Q64.h
#ifndef __W25Q64_H
#define __W25Q64_H
void W25Q64_Init(void);
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID);
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count);
void W25Q64_SectorErase(uint32_t Address);
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count);
//void W25Q64_WriteStatus(void);
#endif
W25Q64.Ins.h
#ifndef __W25Q64_INS_H #define __W25Q64_INS_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 #endif
main.c
#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "W25Q64.h" uint8_t MID; uint16_t DID; uint8_t ArrayWrite[] = {0x01, 0x02, 0x03, 0x04}; uint8_t ArrayRead[4]; int main(void) { OLED_Init(); W25Q64_Init(); // W25Q64_WriteStatus(); OLED_ShowString(1, 1, "MID: DID:"); OLED_ShowString(2, 1, "W:"); OLED_ShowString(3, 1, "R:"); W25Q64_ReadID(&MID, &DID); OLED_ShowHexNum(1, 5, MID, 2); OLED_ShowHexNum(1, 12, DID, 4); W25Q64_SectorErase(0x000000); W25Q64_PageProgram(0x000000, ArrayWrite, 4); W25Q64_ReadData(0x000000, ArrayRead, 4); OLED_ShowHexNum(2, 3, ArrayWrite[0], 2); OLED_ShowHexNum(2, 6, ArrayWrite[1], 2); OLED_ShowHexNum(2, 9, ArrayWrite[2], 2); OLED_ShowHexNum(2, 12, ArrayWrite[3], 2); OLED_ShowHexNum(3, 3, ArrayRead[0], 2); OLED_ShowHexNum(3, 6, ArrayRead[1], 2); OLED_ShowHexNum(3, 9, ArrayRead[2], 2); OLED_ShowHexNum(3, 12, ArrayRead[3], 2); while (1) { } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。