您的位置 首页 数字

STM32 SPI W25X16驱动

前面说了STM32的I2C,作为STM32的另外一个串行接口就不得不提到了——SPI。与I2C差不多,同样有硬件接口,有库函数支持,我们要做的就是

前面说了STM32的I2C,作为STM32的别的一个串行接口就不得不提到了——SPI。与I2C差不多,相同有硬件接口,有库函数支撑,咱们要做的便是结合SPI接口芯片调用库函数,就能完结SPI驱动了。全部看代码,你会懂的,注释十分具体的,很合适初学者。代码可以直接用到实践项目工程里边去的。SPI芯片选用W25X系列。。。

演示作用运用超级终端或许SecureCRT 5.5(这货真的不错)

工程结构图:

1、工程里边的beep.c led.c usart1.c 与《STM32 根据库函数操控按键&nb… 》《STM32 串口例程之查询收》里边彻底相同,这儿就不在上代码。

2、main.c

//程序功用:首要用于测验SPI W25X16驱动是否正常

#include”stm32f10x.h”
#include”user_usart1.h”
#include”user_led.h”
#include”user_beep.h”
#include”user_spi_w25x16.h”
#include

#define FLASH_ID1 0xef3015
#define FLASH_ID2 0xef4015
#define FLASH_WriteAddress 0x000000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorErase FLASH_WriteAddress

#define CountOf(a) (sizeof(a)/sizeof(*(a)))
#define DataSize(CountOf(TxDataTable)-1)

u8 TxDataTable[]=”Hello,I am wgchnln,我 爱 ARM,I will persist in learning ARM,坚决不抛弃”;
u8 RxDataTable[DataSize];

//=============================================
#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
//=============================================

TestStatus User_SPI_DataCompare(u8 *TxData,u8 *RxData,u8 Num)
{
while(Num–)
{
if(*TxData!=*RxData)
{
return Failed;
}
RxData++;
TxData++;
}

return Successed;
}

void User_SPI_Test(void)
{
vu32 ID,DeviceID;
u8 Buffer;
volatile TestStatus Test1=Failed;
volatile TestStatus Test2=Successed; //寄存两次测验的成果


printf(“正在尽力读取ID号…..”);
User_LedSpark(Led1,2);
ID=User_SPI_W25X16_ReadID();
printf(“flashID:%x”,ID);

printf(“正在尽力读取DeviceID号……”);
User_LedSpark(Led1,2);
DeviceID=User_SPI_W25X16_ReadDeviceID();
printf(“flashDeviceID:%x”,DeviceID);



if((ID==FLASH_ID1)||(ID==FLASH_ID2))
{

printf(“ARM在芯片擦除……”);
User_LedSpark(Led1,2);
User_SPI_W25X16_SectorErase(FLASH_SectorErase);
printf(“完结”);


printf(“你要写入的数据:%s”,TxDataTable);
printf(“尽力为你芯片写入中……”);
User_LedSpark(Led1,2);
User_SPI_W25X16_ChipWrite(TxDataTable,FLASH_WriteAddress,DataSize);
printf(“完结”);


printf(“芯片数据读取……”);
User_LedSpark(Led1,2);
User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
printf(“完结”);
User_LedSpark(Led1,2);
printf(“为您读取的数据:%s”,RxDataTable);


printf(“为您做数据比较中……”);
User_LedSpark(Led1,2);
Test1=User_SPI_DataCompare(RxDataTable,TxDataTable,DataSize);
if(Test1==Successed)
{
printf(“数据相同”);
}
else
{
printf(“数据不相同”);
User_LedSpark(Led2,2);
printf(“为您剖析或许原因:数据未写入、读取过错、或许两者一起存在”);
}


printf(“再一次芯片擦除……”);
User_LedSpark(Led1,2);
User_SPI_W25X16_SectorErase(FLASH_SectorErase);
printf(“完结”);


printf(“又一次芯片读取……”);
User_LedSpark(Led1,2);
User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
printf(“完结”);


printf(“判别是否擦除去……”);
User_LedSpark(Led1,1);
for(Buffer=0;Buffer
{
if(RxDataTable[Buffer]!=0xff)
{
Test2=Failed;
}
}
if(Test2==Failed)
{
printf(“失利”);
printf(“为您剖析的或许原因:读取过错、擦除失利、或许两者一起存在”);
}
else
{
printf(“擦除OK”);
}


printf(“————为您展现此次测验成果————“);
if((Test1==Successed)&&((Test2==Successed)))
{
User_LedSpark(Led1,2);
printf(“祝贺你,SPI W25X16驱动测验通过啦”);
}
else
{
User_LedSpark(Led2,2);
printf(“糟糕,SPI功用演示失利了……原因或许是读写数据不一致、软件擦除失利”);
}
}


else
{
User_LedSpark(Led2,2);
printf(“悲惨剧了,SPI功用演示失利啦…..原因是芯片ID号码读取犯错哦”);
}
}

int main(void)
{
User_USART1Config();
printf(“串口1装备……”);
printf(“完结”);

printf(“蜂鸣器初始化…”);
User_BeepConfig();
printf(“蜂鸣器测验……”);
User_BeepStatus(BeepStatus_TurnOn);
printf(“完结”);

printf(“LED初始化…”);
User_LedConfig();
printf(“LED测验……”);
User_LedSpark(Led0,2);
printf(“完结”);

printf(“SPI初始化…”);
User_SPI_Config();
User_LedSpark(Led0,2);
printf(“完结”);

User_SPI_Test();

while(1);
}

//==================================================
PUTCHAR_PROTOTYPE
{


USART_SendData(USART1, (uint8_t) ch);


while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}

return ch;
}
//==================================================

3、user_spi_w25x16.c

//program function:SPI1 Init && FLASF Chip W25X16 driver

#include”stm32f10x.h”
#include”user_spi_w25x16.h”
#include

#define WriteEnable0x06
#define WriteDisable0x04
#define ReadStatusRegister0x05
#define WriteStatusRegister0x01
#define ReadData0x03
#define FastRead0x0b
#define FsatReadDualOutput0x3b
#define PageProgram0x02
#define BlukErase0xd8
#define SectorErase0x20
#define ChipErase0xc7
#define PowerDown0xb9
#define WakeUp0xab
#define DeviceID0xab
#define ManufatureID0x90
#define JedecID0x9f

#define JudgeCode0x01 //用于判别通讯是否完毕用
#define NoneCode0xa5 //无意义的指令,用于:接纳数据时,发送这个质量来发生接纳时分的时钟

void User_SPI_Config(void)
{


SPI_InitTypeDef SPI_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;



RCC_APB2PeriphClockCmd(SPI_24G_CS_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_24G_CS_Pin;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(SPI_24G_CS_Port,&GPIO_InitStructure);
GPIO_SetBits(SPI_24G_CS_Port,SPI_24G_CS_Pin);


RCC_APB2PeriphClockCmd(SPI_VS1003B_CS_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_VS1003B_CS_Pin;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(SPI_VS1003B_CS_Port,&GPIO_InitStructure);
GPIO_SetBits(SPI_VS1003B_CS_Port,SPI_VS1003B_CS_Pin);



RCC_APB2PeriphClockCmd(SPI_W25X16_Clock,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);



RCC_APB2PeriphClockCmd(SPI_W25X16_CS_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_W25X16_CS_Pin;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(SPI_W25X16_CS_Port,&GPIO_InitStructure);
SPI_W25X16_CS_DisSelect;


RCC_APB2PeriphClockCmd(SPI_W25X16_SCK_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_W25X16_SCK_Pin;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(SPI_W25X16_SCK_Port,&GPIO_InitStructure);


RCC_APB2PeriphClockCmd(SPI_W25X16_MISO_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_W25X16_MISO_Pin;
GPIO_Init(SPI_W25X16_MISO_Port,&GPIO_InitStructure);


RCC_APB2PeriphClockCmd(SPI_W25X16_MOSI_Clock,ENABLE);
GPIO_InitStructure.GPIO_Pin =SPI_W25X16_MOSI_Pin;
GPIO_Init(SPI_W25X16_MOSI_Port,&GPIO_InitStructure);



SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex; //通讯形式:双向全双工形式
SPI_InitStructure.SPI_Mode =SPI_Mode_Master;//主从:主形式
SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b;//数据帧长度:8bits
SPI_InitStructure.SPI_CPOL =SPI_CPOL_High;//空闲时置高
SPI_InitStructure.SPI_CPHA =SPI_CPHA_2Edge;//第二个时钟采样
SPI_InitStructure.SPI_NSS =SPI_NSS_Soft;//NSS操控挑选:软件操控
SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2;//波特率分配系数:2分频
SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB;//数据帧格局:MSB在前
SPI_InitStructure.SPI_CRCPolynomial =7;//CRC效验多项式

SPI_Init(SPI1,&SPI_InitStructure);

SPI_Cmd(SPI1,ENABLE);
}

u8 User_SPI_W25X16_SendByte(u8 SendByteData)
{
u8 ReceiveData;


while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);

SPI_I2S_SendData(SPI1,SendByteData);


while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);

ReceiveData=SPI_I2S_ReceiveData(SPI1);

return ReceiveData;
}


u8 User_SPI_W25X16_ReadByte(void)
{
u8 ReceiveData;

ReceiveData=User_SPI_W25X16_SendByte(NoneCode);

return ReceiveData;
}


vu16 User_SPI_W25X16_SendHalfWord(u16 HalfWord)
{
vu16 ReceiveData;


while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);

SPI_I2S_SendData(SPI1,HalfWord);


while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);

ReceiveData=SPI_I2S_ReceiveData(SPI1);

return ReceiveData;
}


void User_SPI_W25X16_WriteEnable(void)
{

SPI_W25X16_CS_Select;


User_SPI_W25X16_SendByte(WriteEnable);


SPI_W25X16_CS_DisSelect;
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/shuzi/259159.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部