⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mm36sb020.c

📁 PIC18F4550_USB开发原代码
💻 C
字号:
/*
综述:
该程序为 MEGAWIN 公司的 mm36sb020 2Mb FLASH 存储芯片读写程序
该产品采用SPI通讯协议


特性、注意:
本程序 FLASH 操作部分为独立的功能模块,互不影响,可自行搭配使用
执行每个基本功能前均需复位:
擦除、从存储器中读取并连续读取、读到缓存、写到缓存并连续写、写到页
mm36sb020_test () 函数体提供对芯片的测试(复位并检测是否忙)
FLASH 芯片采用两线制,需要 BUSY 引脚。两线上需加上拉电阻,将默认电平拉到高

在主程序初始化时应调用 initiate_mm36sb020 进行初始化,如:
	mm36sb020_OE_tris = 1;
	initiate_mm36sb020 ();					// 初始化

本程序完全不考虑 OE ,可自行在主程序中对FLASH操作前添加,如:
	mm36sb020_OE_tris = 1;
	if (!mm36sb020_OE)	return (FALSE);
	mm36sb020_OE_lat = 0;
	mm36sb020_OE_tris = 0;
	initiate_mm36sb020 ();
	if (mm36sb020_test() == FALSE)	return (FALSE);	// 如FLASH无响应,返回
	mm36sb020_reset();
	……………………
对FLASH存储器的所有操作完成后应执行mm36sb020_test (),将芯片复位
操作完毕后应释放所有资源,如:
	mm36sb020_test ();
	initiate_mm36sb020 ();
	mm36sb020_OE_tris = 1;
	……………………

本程序需要定义主时钟
成功调试环境:MCU主频16MHz,18F448,MPLAB C18 Student-Edition Compiler 2.40
本程序不涉及中断,采用等待延时,失败后只返回错误
本程序中延时部分须注意看门狗复位


接口、说明:
由于编译器不稳定,本程序需外部调用的函数传参部分大于int型的量使用指针传送,并一律返回int型,请注意
本程序调用 initiate_mm36sb020 进行初始化,返回正常
调用mm36sb020_write_nbytes 实现写n个字节。(1<=n<=16)
调用mm36sb020_read_nbytes 实现读n个字节。(1<=n<=255)
这两个函数限制很大,使用时需小心


需要定义(默认在 ..\Resources.h 中):
#define MainOSC			4					// 主频(1-16Mhz),4MHz

#define TRUE			1					// 真
#define FALSE			-1					// 假

#define mm36sb020_OE_tris	TRISCbits.TRISC0	// FLASH 芯片
#define mm36sb020_OE_lat	LATCbits.LATC0		// mm36sb020
#define mm36sb020_OE		PORTCbits.RC0		// OE 引脚定义

#define mm36sb020_BUSY_tris	TRISCbits.TRISC1	// BUSY
#define mm36sb020_BUSY		PORTCbits.RC1		// 引脚定义

#define mm36sb020_SCL_tris	TRISCbits.TRISC6	// SCL
#define mm36sb020_SCL_lat	LATCbits.LATC6		// 引脚定义

#define mm36sb020_SDA_tris	TRISCbits.TRISC7	// 
#define mm36sb020_SDA_lat	LATCbits.LATC7		// SDA
#define mm36sb020_SDA		PORTCbits.RC7		// 引脚定义

*/



#include <p18cxxx.h>
#include "..\Resources.h"

#define ERSC	0x90F6					// ERaSe whole Chip
#define SRC		0xFFFFFFFE				// Software Reset Chip
#define RSE		0x94					// Read Status to External
#define RBE		0x98					// Read Buffer to External
#define RME		0x9C					// Read flash Memory to External
#define RMEC	0xA0					// Continusly Read Byte from Main Storage
#define RMB		0xA4					// Read page from flash Memory to Buffer
#define WEB		0xA8					// Write External data to Buffer
#define WEBC	0xAC					// Continusly Write External data to Buffer
#define WBMEP	0xB0					// Write Buffer to Main Storage with Erase
#define WBMP	0xB4					// Write Buffer to Main Storage



int initiate_mm36sb020 (void);								// 初始化,返回正常
int mm36sb020_test (void);									// 自检测试
void mm36sb020_read_nbytes (unsigned long *, unsigned char *, unsigned char);
					// 从某地址读取n字节(地址指针,最多16字节头指针, n个字节)
int mm36sb020_write_nbytes (unsigned long *, unsigned char *, unsigned char);
					// 向某地址写入n字节(地址指针,最多16字节头指针, n个字节)

/*	-------------- 独立基本功能模块函数声明 --------------	*/

void mm36sb020_write_bits (unsigned long, unsigned char);	// 写入位(命令字,长度)	内部调用
unsigned char mm36sb020_read_bits (void);					// 读出位				内部调用
void mm36sb020_write_data_bits (unsigned char);				// 写入位(8位命令字,快速无延时)	内部调用

void mm36sb020_reset (void);								// 复位
int mm36sb020_erase (void);									// 芯片擦除
int mm36sb020_read_from_memory (unsigned int *, unsigned char);	// 从 flash 中读一字节(页指针,地址指针)
int mm36sb020_read_continusly (void);						// 连续读取
int mm36sb020_read_to_buffer (unsigned int *);				// 从 flash 中读到缓存(页指针)
void mm36sb020_write_to_buffer (unsigned char, unsigned char);	// 向缓存中写一字节(地址指针,字节指针)
void mm36sb020_write_continusly (unsigned char);			// 连续写入(字节指针)
int mm36sb020_write_from_buffer (unsigned int *);			// 从缓存中写到 flash(页指针)

/*	-------------------- 延时部分 ------------------------	*/

void delay5times (void);					// 延时5个指令周期
void delay25times (void);					// 延时25个指令周期
void delay40us (void);						// 延时40微秒多
void delay500us (void);						// 延时500微秒多
void delaynms (unsigned char);				// 延时n(1-250)毫秒多,注意看门狗

void delay5times (void)
{	Nop ();		}
void delay25times (void)
{	delay5times ();		delay5times ();
	delay5times ();		delay5times ();
	Nop ();		}
void delay40us (void)
{
	unsigned char roundtimes;
	roundtimes = MainOSC;
	while (roundtimes!=0)
	{
		delay5times ();
		delay5times ();
		roundtimes--;
	};
}
void delay500us (void)
{
	unsigned char roundtimes;
	roundtimes = MainOSC;
	while (roundtimes!=0)
	{
		delay25times ();
		delay25times ();
		delay25times ();
		delay25times ();
		delay25times ();
		roundtimes--;
	};
}
void delaynms (unsigned char mstimes)
{
	while (mstimes!=0)
	{
		delay500us ();
		delay500us ();
		mstimes--;
	};
}


/*	---------------- 独立基本功能模块 --------------------	*/


void mm36sb020_write_bits (unsigned long databits, unsigned char bitslength)
{									// 向 SPI 引脚写入位(命令字,长度)			内部调用
	mm36sb020_SCL_tris = 1;			// 预置时钟引脚为高电平
	mm36sb020_SCL_lat = 0;			// 时钟 lat 为低电平
	mm36sb020_SDA_tris = 1;			// 预置数据引脚为高电平
	mm36sb020_SDA_lat = 0;			// 数据 lat 为低电平

	while (bitslength!=0)			// 循环 bitslength 位次
	{
		mm36sb020_SDA_tris = databits & 0x00000001;	// 由低到高顺序置 SDA 电平
		mm36sb020_SCL_tris = 0;						// 时钟下降沿
		databits = databits >> 1;					// 数据右移
		delay25times ();
		mm36sb020_SCL_tris = 1;						// 时钟上升沿,数据移入
		bitslength--;								// 循环次数减一
		delay25times ();
	};
	mm36sb020_SDA_tris = 1;							// 恢复 SDA 默认状态
}


unsigned char mm36sb020_read_bits (void)
{												// 从 SPI 引脚读出位			内部调用
	unsigned char received,i=8;

	mm36sb020_SCL_tris = 1;						// 预置时钟引脚为高电平
	mm36sb020_SCL_lat = 0;						// 时钟 lat 为低电平
	mm36sb020_SDA_tris = 1;						// 预置数据引脚为输入

	while (i!=0)								// 循环 8 次
	{
		mm36sb020_SCL_tris = 0;					// 时钟引脚 下降沿
		received = received >> 1;				// 先收LSB,收到的字节右移一位
		i--;									// 循环次数减一
		mm36sb020_SCL_tris = 1;					// 时钟引脚 上升沿,数据移出
		Nop ();
		if (mm36sb020_SDA)						// 判断高低电平:
		{	received |= 0x80;	}				// 为高(1)
		else
		{	received |= 0x00;	};				// 为低(0)
	};

	return (received);							// 返回收到的字节
}


void mm36sb020_write_data_bits (unsigned char databits)
{									// 向 SPI 引脚写入位(8位命令字,无延时)			内部调用
	unsigned char i=8;
	mm36sb020_SCL_tris = 1;			// 预置时钟引脚为高电平
	mm36sb020_SCL_lat = 0;			// 时钟 lat 为低电平
	mm36sb020_SDA_tris = 1;			// 预置数据引脚为高电平
	mm36sb020_SDA_lat = 0;			// 数据 lat 为低电平

	while (i!=0)					// 循环 8 位次
	{
		mm36sb020_SDA_tris = databits & 0x01;		// 由低到高顺序置 SDA 电平
		mm36sb020_SCL_tris = 0;						// 时钟下降沿
		databits = databits >> 1;					// 数据右移
		mm36sb020_SCL_tris = 1;						// 时钟上升沿,数据移入
		i--;										// 循环次数减一
	};
	mm36sb020_SDA_tris = 1;							// 恢复 SDA 默认状态
}





void mm36sb020_reset (void)
{												// 复位
	mm36sb020_write_bits (SRC,32);				// 发送32位的复位命令
}


int mm36sb020_erase (void)
{												// 芯片擦除
	mm36sb020_write_bits (ERSC,16);				// 发送16位的擦除命令
	delay25times ();
	mm36sb020_SCL_tris = 0;						// 时钟下降沿,执行擦除命令
	delay5times ();
	mm36sb020_SCL_tris = 1;						// 恢复 SCL 默认状态
	if (!mm36sb020_BUSY)	return (FALSE);		// 如 BUSY 位为零(不忙),返回错误
										ClrWdt ();
	delaynms (40);								// 延时 35ms
										ClrWdt ();
	if (mm36sb020_BUSY)	return (FALSE);			// 如 BUSY 位不为零(忙),返回错误
	return (TRUE);								// 返回正常
}


int mm36sb020_read_from_memory (unsigned int *mm36sb020_page, unsigned char mm36sb020_address)
{												// 从 flash 中读一字节(页指针,地址指针)
	mm36sb020_write_bits (RME,8);				// 发送8位的读取命令
	mm36sb020_write_bits (mm36sb020_address,8);	// 发送8位的地址
	mm36sb020_write_bits (*mm36sb020_page,16);	// 发送16位的页号
	return ( mm36sb020_read_bits() );			// 返回读到的字节
}


int mm36sb020_read_continusly (void)
{												// 接上面函数,连续读取
	mm36sb020_write_data_bits (RMEC);			// 发送8位的连续读取命令
	return ( mm36sb020_read_bits() );			// 返回读到的字节
}


int mm36sb020_read_to_buffer (unsigned int *mm36sb020_page)
{												// 从 flash 中读到缓存(页指针)
	mm36sb020_write_bits (RMB,8);				// 发送8位的读取命令
	mm36sb020_write_bits (*mm36sb020_page,16);	// 发送16位的页号

	delay25times ();
	mm36sb020_SCL_tris = 0;						// 时钟下降沿,执行读取命令
	delay5times ();
	mm36sb020_SCL_tris = 1;						// 恢复 SCL 默认状态
	if (!mm36sb020_BUSY)	return (FALSE);		// 如 BUSY 位为零(不忙),返回错误
	delay40us ();
	delay40us ();								// 延时 70us
	if (mm36sb020_BUSY)	return (FALSE);			// 如 BUSY 位不为零(忙),返回错误
	return (TRUE);								// 返回正常
}


void mm36sb020_write_to_buffer (unsigned char mm36sb020_address, unsigned char databyte)
{												// 向缓存中写一字节(地址指针,字节指针)
	mm36sb020_write_bits (WEB,8);				// 发送8位的写入命令
	mm36sb020_write_bits (mm36sb020_address,8);	// 发送8位的地址
	mm36sb020_write_bits (databyte,8);			// 发送8位的写入数据
}


void mm36sb020_write_continusly (unsigned char databyte)
{												// 接上面函数,连续写入
	mm36sb020_write_bits (WEBC,8);				// 发送8位的连续写入命令
	mm36sb020_write_bits (databyte,8);			// 发送8位的写入数据
}


int mm36sb020_write_from_buffer (unsigned int *mm36sb020_page)
{												// 从缓存中写到 flash(页指针)
	mm36sb020_write_bits (WBMEP,8);				// 发送8位的写入命令
	mm36sb020_write_bits (*mm36sb020_page,16);	// 发送16位的页号

	delay25times ();
	mm36sb020_SCL_tris = 0;						// 时钟下降沿,执行写入命令
	delay5times ();
	mm36sb020_SCL_tris = 1;						// 恢复 SCL 默认状态
	if (!mm36sb020_BUSY)	return (FALSE);		// 如 BUSY 位为零(不忙),返回错误
										ClrWdt ();
	delaynms (15);								// 延时 12ms
	if (mm36sb020_BUSY)	return (FALSE);			// 如 BUSY 位不为零(忙),返回错误
	return (TRUE);								// 返回正常
}

/*	------------------------------------------------------	*/


int mm36sb020_test (void)
{											// 自检测试
	mm36sb020_reset ();						// 复位

	delay25times ();
	mm36sb020_SCL_tris = 0;					// 时钟下降沿,执行复位命令
	delay5times ();
	mm36sb020_SCL_tris = 1;					// 恢复 SCL 默认状态
	if (!mm36sb020_BUSY)	return (FALSE);		// 如 BUSY 位为零(不忙),返回错误
	delay40us ();								// 延时 32us
	if (mm36sb020_BUSY)	return (FALSE);			// 如 BUSY 位不为零(忙),返回错误
	return (TRUE);								// 返回正常
}


int initiate_mm36sb020 (void)
{
	mm36sb020_BUSY_tris = 1;				// BUSY 置为输入
	mm36sb020_SCL_lat = 0;					// 时钟 lat 为低电平
	mm36sb020_SDA_lat = 0;					// 数据 lat 为低电平
	mm36sb020_SCL_tris = 1;					// 预置时钟引脚为默认高电平
	mm36sb020_SDA_tris = 1;					// 预置数据引脚为默认高电平
	return (TRUE);							// 返回正常
}


void mm36sb020_read_nbytes (unsigned long *mm36sb020_whole_address, unsigned char *data_pointer, unsigned char n)
{											// 从某地址读取n字节(地址指针,最多16字节头指针, n个字节)
	unsigned int page;
	unsigned char num,i;

	page = (*mm36sb020_whole_address)/0x80;							// 求出页号
	num = (*mm36sb020_whole_address % 0x80) & 0x70;					// 求出页内地址

	mm36sb020_reset();												// 复位

	data_pointer[0] = mm36sb020_read_from_memory (&page,num);		// 读取第一个字节
	i=1;
	while (i!=n)													// n个字节
	{
		data_pointer[i] = mm36sb020_read_continusly ();				// 连续读取n个字节
		i++;
	};
}


int mm36sb020_write_nbytes (unsigned long *mm36sb020_whole_address, unsigned char *data_pointer, unsigned char n)
{											// 向某地址写入n字节(地址指针,最多16字节头指针, n个字节)
	unsigned int page;
	unsigned char num,i;

	page = (*mm36sb020_whole_address)/0x80;							// 求出页号
	num = (*mm36sb020_whole_address % 0x80) & 0x70;					// 求出页内地址

	mm36sb020_reset();												// 复位
	if (mm36sb020_read_to_buffer(&page) == FALSE)	return (FALSE);	// 将该页读入缓存

	mm36sb020_reset();												// 复位
	mm36sb020_write_to_buffer (num,data_pointer[0]);
	i=1;
	while (i!=n)													// n个字节
	{
		mm36sb020_write_continusly (data_pointer[i]);				// 字节递加
		i++;
	};																// 将n个字节写入缓存

	mm36sb020_reset();												// 复位
	if (mm36sb020_write_from_buffer(&page) == FALSE)	return (FALSE);	// 将缓存回写入该页

	return (TRUE);													// 返回正常
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -