/*
編輯框架:
基礎層===》隔離層===》驅動層===》應用層
基礎層:包含管腳初始化,配置管腳輸入輸出腳的基礎函數到隔離層
例如:void FM25_IOInit(void);
void FM25_CS(u8 IO);
void FM25_CLK(u8 IO);
void FM25_MOSI(u8 IO);
u8 FM25_MISO(void);
隔離層:操作隔離
例如:
//隔離初始化
SPI_Type FM25_SPI = {
.CS = FM25_CS,
.CLK = FM25_CLK,
.MOSI = FM25_MOSI,
.MISO = FM25_MISO};
最好再添加一個函數包裹着 u8 Soft_SPI_RW(SPI_Type *BaseSPI, u8 dat)函數,減少FM25_SPI 耦合
eg:
u8 SPI_Send_Byte( u8 WRDat )
{
return Soft_SPI_RW( FM25_SPI, WRDat ); //軟件模擬讀寫一字節
}
驅動層:就是芯片的時序讀寫
應用層: 驅動層提供芯片封裝好的應用函數給永輝
*/
typedef struct _SPI
{
//SPI管腳
void (*CS)(u8) ; //片選腳輸出
void (*CLK)(u8) ; //時鐘腳輸出
void (*MOSI)(u8) ; //輸出
u8(*MISO)(void) ; //輸入
} SPI_Type;
/**
* @Name soft_SPI_Write
* @brief 模擬SPI讀寫一字節
* @param BaseSPI: [輸入]
** dat: [輸入]
* @retval
* @author https://blog.csdn.net/Wekic
* @Data 2020-03-29
**/
u8 Soft_SPI_RW(SPI_Type BaseSPI, u8 dat)
{
u8 i = 0;
u8 temp = 0;
for(i = 0; i < 8; i++) {
if(BaseSPI.CLK) {BaseSPI.CLK(0);} //上升沿移送數據
if((dat << i) & 0x80) { //數據輸出
if(BaseSPI.MOSI) {BaseSPI.MOSI(1);}
} else {
if(BaseSPI.MOSI) {BaseSPI.MOSI(0);}
}
if(BaseSPI.CLK) {BaseSPI.CLK(1);} //移送數據
temp<<=1;
if(BaseSPI.MISO && BaseSPI.MISO()) //數據輸入
{
temp |=1;
}
}
return (temp); //返回數據
}
----------------------------------------------------------------------------------------------------------------------------
2020-03-30:增加軟件模擬SPI應用文件----FM25CL64芯片操作
FM25CL64.h
/**
************************************* Copyright ******************************
* (C) Copyright 2020,Wenkic,China, GCU.
* All Rights Reserved
*
* By(Wenkic)
* https://blog.csdn.net/Wekic
*
* FileName : FM25CL64.h
* Version : v1.0
* Author : Wenkic
* Date : 2020-03-30
* Description:
* Function List:
******************************************************************************
*/
#ifndef __FM25CL64_H
#define __FM25CL64_H
#include "stm32f10x.h"
//================================================
// 基礎層
//================================================
void FM25_IOInit(void); //管腳初始化
//================================================
// 應用層
//================================================
u8 FM25ReadByte(u16 Addr); //單數據寫入
void FM25WriteByte(u16 Addr,u8 Wdat); //單數據讀取
void FM25WriteString(u16 WAddr, u8 *WDat ,u16 len); //寫入一串數據
void FM25ReadString(u16 WAddr, u8 *RDat ,u16 len); //讀出一串數據
#endif
FM25CL64.c
/*
************************************* Copyright ******************************
*
* (C) Copyright 2020,Wenkic,China, GCU.
* All Rights Reserved
*
* By(Wenkic)
* https://blog.csdn.net/Wekic
*
* FileName : FM25CL64.c
* Version : v1.0
* Author : Wenkic
* Date : 2020-03-29
* Description: FM25CL64 鐵電存儲驅動
* Function List:
******************************************************************************
*/
/********************************End of Head************************************/
#include "sys.h"
#include "FM25CL64.h"
#include "Soft_SPI.h"
//基礎層函數聲明============
void FM25_IOInit(void);
void FM25_CS(u8 IO);
void FM25_CLK(u8 IO);
void FM25_MOSI(u8 IO);
u8 FM25_MISO(void);
//==========================
//管腳定義宏================
#define FM_CS PAout(4)
#define FM_CLK PAout(5)
#define FM_MOSI PAout(7)
#define FM_MISO PAin(6)
//================================================
// 接口隔離層
//================================================
SPI_Type FM25_SPI = {
.CS = FM25_CS,
.CLK = FM25_CLK,
.MOSI = FM25_MOSI,
.MISO = FM25_MISO,
};
//SPI寫
void FM25_WriteSPIByte(u8 dat)
{
Soft_SPI_RW( FM25_SPI, dat); //軟件模擬讀寫一字節
}
//SPI讀
u8 FM25_ReadSPIByte(void)
{
return Soft_SPI_RW( FM25_SPI, 0xFF); //軟件模擬讀寫一字節
}
//CS片選隔離
void FM25_CS_Out(u8 IO)
{
IO?(FM25_SPI.CS(1)):(FM25_SPI.CS(0));
}
//==================================================
// 基礎層
//==================================================
void FM25_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
FM_CS = 1;
FM_CLK = 1;
FM_MOSI = 1;
//CS,CLK,MOSI
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//MISO
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
FM_CS = 1;
FM25_ReadSPIByte(); //試讀一次
}
//片選IO控制
void FM25_CS(u8 IO)
{
FM_CS = IO?1:0;
}
//片選IO控制
void FM25_CLK(u8 IO)
{
FM_CLK = IO?1:0;
}
//片選IO控制
void FM25_MOSI(u8 IO)
{
FM_MOSI = IO?1:0;
}
//片選IO控制
u8 FM25_MISO(void)
{
return (FM_MISO?1:0);
}
//================================================
// 驅動層
//================================================
#define FM25_DELAY_CNT 10
//FM25L16B命令
#define FM25_WREN 0x06 //寫使能
#define FM25_WRDI 0x04 //寫禁止
#define FM25_RDSR 0x05 //讀狀態寄存器
#define FM25_WRSR 0x01 //寫狀態寄存器
#define FM25_READ 0x03 //讀存儲器數據
#define FM25_WRITE 0x02 //寫存儲器數據
/**
* @Name FM25CL_WriteEnable
* @brief FM25寫使能
**/
void FM25CL_WriteEnable(void)
{
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_WREN);
FM25_CS_Out(1); //拉高CS
}
/**
* @Name FM25CL_WriteDisable
* @brief FM25寫禁止
**/
void FM25CL_WriteDisable(void)
{
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_WRDI);
FM25_CS_Out(1); //拉高CS
}
/**
* @Name FM25CL_ReadReg
* @brief 讀取狀態寄存器命令
**/
u8 FM25CL_ReadReg(void)
{
u8 temp;
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_RDSR); //0x05命令
temp = FM25_ReadSPIByte(); //讀出數據
FM25_CS_Out(1); //拉高CS
return temp;
}
/**
* @Name FM25CL_WriteReg
* @brief 寫狀態寄存器命令
**/
void FM25CL_WriteReg(u8 reg)
{
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_WRSR); //0x01命令
FM25_WriteSPIByte(reg); //寫入數據
FM25_CS_Out(1); //拉高CS
}
/**
* @Name FM25CL_ReadByte
* @brief 讀取數據
**/
u8 FM25CL_ReadByte(u16 Addr)
{
u8 temp;
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_READ); //0x03命令
FM25_WriteSPIByte((Addr>>8)&0xFF); //地址高位
FM25_WriteSPIByte((Addr>>0)&0xFF); //地址低位
temp = FM25_ReadSPIByte(); //讀取數據
FM25_CS_Out(1); //拉高CS
return temp;
}
/**
* @Name FM25CL_WriteByte
* @brief 寫入數據
**/
void FM25CL_WriteByte(u16 Addr,u8 dat)
{
FM25CL_WriteEnable(); //寫使能
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_WRITE); //0x02命令
FM25_WriteSPIByte((Addr>>8)&0xFF); //地址高位
FM25_WriteSPIByte((Addr>>0)&0xFF); //地址低位
FM25_WriteSPIByte(dat); //寫入數據
FM25_CS_Out(1); //拉高CS
}
/**
* @Name FM25CL_ReadString
* @brief 連續讀取數據
**/
void FM25CL_ReadString(u16 Addr,u8 *dat,u16 len)
{
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_READ); //0x03命令
FM25_WriteSPIByte((Addr>>8)&0xFF); //地址高位
FM25_WriteSPIByte((Addr>>0)&0xFF); //地址低位
while(len--)
{
*dat = FM25_ReadSPIByte(); //讀取數據
dat++;
}
FM25_CS_Out(1); //拉高CS
}
/**
* @Name FM25CL_WriteString
* @brief 連續寫入數據
**/
void FM25CL_WriteString(u16 Addr,u8 *dat,u16 len)
{
FM25CL_WriteEnable(); //寫使能
FM25_CS_Out(0); //拉低CS
FM25_WriteSPIByte(FM25_WRITE); //0x02命令
FM25_WriteSPIByte((Addr>>8)&0xFF); //地址高位
FM25_WriteSPIByte((Addr>>0)&0xFF); //地址低位
while(len--)
{
FM25_WriteSPIByte(*dat); //寫入數據
dat++;
}
FM25_CS_Out(1); //拉高CS
}
//================================================
// 應用層
//================================================
/**
* @Name FM25WriteByte
* @brief 寫入單數據
**/
void FM25WriteByte(u16 Addr,u8 Wdat)
{
FM25CL_WriteByte( Addr, Wdat);
}
/**
* @Name FM25ReadByte
* @brief 讀取單數據
**/
u8 FM25ReadByte(u16 Addr)
{
return FM25CL_ReadByte(Addr);
}
/**
* @Name FM25CL_WriteString
* @brief 連續寫入數據
**/
void FM25WriteString(u16 WAddr, u8 *WDat,u16 len)
{
void FM25WriteString(u16 WAddr, u8 *WDat,u16 len)
{
FM25CL_WriteString( WAddr, WDat, len);
}
}
/**
* @Name FM25ReadString
* @brief 連續寫入數據
**/
void FM25ReadString(u16 WAddr, u8 *RDat,u16 len)
{
FM25CL_ReadString( WAddr, RDat, len);
}
/********************************End of File************************************/