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

📄 flash.c

📁 此文档是网上一款开发板的完整系统,内附有电路图纸!系统有完整的接口程式,包含了字符型LCD驱动,pc串口通讯程式,flash读写驱动程式,中文字库,ad芯片驱动程式,keyscan4*4扫描程式
💻 C
字号:
//**********************************************************************************
//**********************************************************************************
//SST39F020的读写函数
#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long
#include <reg52.h>
#include "study.h"
//***********************************************************
//读N个flash中的字节,每次最多65535字节
//入口:在flash中的物理地址,读出来放在内存中的指针首位置,读出多少个字节
readeprom(ulong ad,uchar *pst,uint n)
{
	union {ulong addr_l;struct {uint a32;uint a10;}addr_i;struct {uchar a3;uint a21;uchar a0;}addr;} address;
 	uint i;
	uchar xdata *flash;
	//uchar savep1;
	
	//savep1=P1;              
	P1=0xff;				//P1口如被占用暂停读取
	while(P1!=0xff);
	address.addr_l=ad;
	P1=(P1&0xc0) | (address.addr.a21/0x20);	//设置bank线,每块8K字节
	flash=0x8000+address.addr_i.a10%0x2000; //flash窗口地址范围0x8000-0x9ffff
	for(i=0;i<n;i++)  //读N个字节
	{
		*(pst++)=*(flash++);
		if(flash==0xa000) //如果地址跨页则翻到下一个bank
		{
			P1++;
			flash=0x8000;
		}
	}
	//P1=savep1;
}

//*********************************
//读全部flash数据,从串口输出
void readflash(void)
{
	union {ulong addr_l;struct {uchar a3;uchar a2;uint a10;}addr_i;struct {uchar a3,a2,a1,a0;}addr;} address;
	uchar xdata c[1];//用来读一个字节的缓存
	uchar *pst=c;
	
	cls(8);setcursor(0,0);	//清屏,设置光标到左上方
	lcdstring("波特率38400bps.按任意键开始发送。"); //输出提示到液晶
	while(getkey(1000)==0);  //等待按键
	cls(8);setcursor(0,0);	 //提示正在发送
	lcdstring("数据正在从串口发送... 按任意键结束");
	putstring("以下是大虾51学习板中flash中的内容\r\n");	
	address.addr_l=0x00000; //读出全部的数据,起始地址为0
	do
	{
		if (address.addr.a0%16==0)
		{	//输出格式,每16个字符一行,输出地址,形成HEX形式数据
			CR;puthex(address.addr.a2);puthex(address.addr.a1);puthex(address.addr.a0);putbyte(':');
		}
		readeprom(address.addr_l,pst,1);  //读出一个字节
		puthex(*pst); //输出改字节的HEX码
		putbyte(' ');  //输出一个空格,格开每个字节
		address.addr_l++; //地址加一
	}while(getkey(1)==0); //没有按键继续发送
}

//**************************************
//擦除flash块,地址为0xffffffff时执行片擦,其他地址擦除当前位置的4K字节块
//入口:要擦除的地址
void erasesector(ulong addr)
{	
	//定义一个联合,以便地址计算更快速
	union {ulong addr_l;struct {uchar a3;uchar a2;uint a10;}addr_i;struct {uchar a3;uint a21;uchar a0;}addr;} address;
	uint delay;		 
	uchar xdata *pst; //定义个指向外部xdata的指针

	P1=0xff;         //如果P1被占用则等待
	while(P1!=0xff);   

	address.addr_l=addr;  

	pst=0x8000+0x5555%0x2000; //往flash写入钥匙串
	P1=(P1&0xc0) | (0x55>>5);
	*pst=0xaa;
	
	pst=0x8000+0x2aaa%0x2000;
	P1=(P1&0xc0) | (0x2a>>5);
	*pst=0x55;
	
	pst=0x8000+0x5555%0x2000;
	P1=(P1&0xc0) | (0x55>>5);
	*pst=0x80;
	

	pst=0x8000+0x5555%0x2000;
	P1=(P1&0xc0) | (0x55>>5);
	*pst=0xaa;
	
	pst=0x8000+0x2aaa%0x2000;
	P1=(P1&0xc0) | (0x2a>>5);
	*pst=0x55;

	if(addr==0xffffffff)     //如果地址是0xffffffff则改为片擦,这是为了方便,省得多做一个函数
	{
		pst=0x8000+0x5555%0x2000; //片擦
		P1=(P1&0xc0) | (0x55>>5);
		*pst=0x10;
	}
	else
	{
		pst=0x8000+address.addr_i.a10%0x2000;  //按照输入的地址擦除当前所在的块
		P1=(P1&0xc0) | (address.addr.a21/0x20);	
		*pst=0x30;
	}
	for(delay=0;delay<20000;delay++);  //延时等待写入完成
}

//**************************
//在flash中写入一个字节
//入口:写入的地址,写入的字节
void writeflash(ulong addr_w,uchar ch)
{
	union {ulong addr_l;struct {uchar a3;uchar a2;uint a10;}addr_i;struct {uchar a3;uint a21;uchar a0;}addr;} address;
	uchar xdata *pst;

	P1=0xff;   //P1如被占用等待
	while(P1!=0xff);

	address.addr_l=addr_w;

	pst=0x8000+0x5555%0x2000;  //输入钥匙串
	P1=(P1&0xc0) | (0x55>>5);
	*pst=0xaa;
	
	pst=0x8000+0x2aaa%0x2000;
	P1=(P1&0xc0) | (0x2a>>5);
	*pst=0x55;
	
	pst=0x8000+0x5555%0x2000; 
	P1=(P1&0xc0) | (0x55>>5);
	*pst=0xa0;

	pst=0x8000+address.addr_i.a10%0x2000;  //输入地址和数据
	P1=(P1&0xc0) | (address.addr.a21/0x20);	
	*pst=ch;

}

//******************************
//写入一个文件,需要从计算机串口输出
void write_file(void)
{
	ulong n;
	uint x;
	uchar ch;

	cls(8);	setcursor(0,0);	//清屏,光标移到左上角
	lcdstring("警告!写错文件会导致汉字无法显示!");
	while((ch=getkey(1000))==0x00); //等待按键
	if(ch!='Y') return;				//如果收到Cancel键则退出
	cls(8);	setcursor(0,0);	 		
	lcdstring("波特率38400bps,等待计算机发送文件.");
	while(inbufsign)getbyte();	 //清除串口缓冲
	putstring("\r\n请将光标放在计算机串口调试软件接收窗口.然后在计算机键盘输入擦除密码:2816\r\n");	

	if(getbyte()=='2') 
	{
		if(getbyte()=='8')
		{
			if(getbyte()=='1')
			{
				if(getbyte()=='6')
				{
					putstring("\r\n密码正确,正在擦除学习板flash中的内容,请继续后面的发送字库文件的操作,否则液晶将无法显示!");
					erasesector(0xffffffff);	//擦除整块flash
				
					putstring("\r\n擦除完成,请选择好要发送的文件,点'发送'输出到串口,发送之前不要按计算机键盘.");	
				
					while(!inbufsign);
				
					for(n=0;n<0x80000;n++)		//最大烧写512K字节
					{
						x=0;
						while(!inbufsign) 
						{
							x++;
							if(x>60000) goto isOut; //接收超时退出
						}
						writeflash(n,getbyte());
					 }
isOut:				putstring("\r\n烧写完毕!");
					return;
				 }//end of if(getbyte()!='6') 

			  }
		  }
		  
	 }
	 putstring("\r\n密码错误!请复位单片机重新来过."); return;
}

⌨️ 快捷键说明

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