【STM32学习】 | 您所在的位置:网站首页 › stm32软著 › 【STM32学习】 |
四、软件SPI读写W25Q64
工程思路与I2C类似,MySPI.c是通信底层,主要包括通信引脚封装、初始化、SPI通信的三个拼图(起始、终止和交换一个字节);基于此文件建立W25Q64.c,调用MySPI三个拼图,拼接成各种指令和功能的完整时序,如写使能、擦除、页编程、读数据等,可看作W25Q64芯片的硬件驱动层。在主函数调用驱动层函数: //MySPI.c #include "stm32f10x.h" void MySPI_W_SS(uint8_t BitValue){//SS或CS,片选或从机选择。 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_GPIOC,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> i);//放到线上。与从机同步的 MySPI_W_SCK(1);//线上的数据被分别读走(交换) if(MySPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}//主机接收到的数据位存到ByteReceive MySPI_W_SCK(0); } return ByteReceive; } //0x80 >> i的作用是用来挑出数据的某一位或者某几位(或屏蔽其他的无关位,是掩码操作思想)。好处是没改变传入参数ByteSend //另一种更简洁的方法,但会改变ByteSend变量: //uint8_t MySPI_SwapByte(uint8_t ByteSend){ // uint8_t i; // for(i=0;i 16); MySPI_SwapByte(Address >>8); MySPI_SwapByte(Address); MySPI_Stop(); W25Q64_WaitBusy();//等待Busy(注意事项) } 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> 8); //交换发送地址15~8位 MySPI_SwapByte(Address); //交换发送地址7~0位 for (i = 0; i < Count; i ++) //循环Count次 { MySPI_SwapByte(DataArray[i]); //依次在起始地址后写入数据 } MySPI_Stop(); //SPI终止 W25Q64_WaitBusy(); //等待忙 } /** * 函 数:W25Q64扇区擦除(4KB) * 参 数:Address 指定扇区的地址,范围:0x000000~0x7FFFFF * 返 回 值:无 */ void W25Q64_SectorErase(uint32_t Address) { W25Q64_WriteEnable(); //写使能 MySPI_Start(); //SPI起始 MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB); //交换发送扇区擦除的指令 MySPI_SwapByte(Address >> 16); //交换发送地址23~16位 MySPI_SwapByte(Address >> 8); //交换发送地址15~8位 MySPI_SwapByte(Address); //交换发送地址7~0位 MySPI_Stop(); //SPI终止 W25Q64_WaitBusy(); //等待忙 } /** * 函 数:W25Q64读取数据 * 参 数:Address 读取数据的起始地址,范围:0x000000~0x7FFFFF * 参 数:DataArray 用于接收读取数据的数组,通过输出参数返回 * 参 数:Count 要读取数据的数量,范围:0~0x800000 * 返 回 值:无 */ void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) { uint32_t i; MySPI_Start(); //SPI起始 MySPI_SwapByte(W25Q64_READ_DATA); //交换发送读取数据的指令 MySPI_SwapByte(Address >> 16); //交换发送地址23~16位 MySPI_SwapByte(Address >> 8); //交换发送地址15~8位 MySPI_SwapByte(Address); //交换发送地址7~0位 for (i = 0; i < Count; i ++) //循环Count次 { DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE); //依次在起始地址后读取数据 } MySPI_Stop(); //SPI终止 }由于涉及的文件较多,这里不全部列举,下面是文件下载链接: 百度网盘打开 |
CopyRight 2018-2019 实验室设备网 版权所有 |