軟件模擬SPI基礎函數--以及一些框架思想

/*
編輯框架:
  基礎層===》隔離層===》驅動層===》應用層

基礎層:包含管腳初始化,配置管腳輸入輸出腳的基礎函數到隔離層
   例如: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************************************/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章