/*
编辑框架:
基础层===》隔离层===》驱动层===》应用层
基础层:包含管脚初始化,配置管脚输入输出脚的基础函数到隔离层
例如: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************************************/