📄 flash.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 + -