51单片机EEPROM(E2PROM)测试程序,发送到串口 带独立波特率发生器测试

/************************************************************************************
*
* 文件名称: eeprom.c 


* 摘 要:    对EEPROM某个扇区进行读、写和擦除,并发送到串口
			 UART=9600 8位数据 CRYSTAL=18.432 TIMER_MODE=12T
			 (EEPROM就是DATA FLASH,擦除只能按扇区,读写可以按字节,字节为0XFF时才可以写)


* CPU芯片:  STC12C5A16S2	  instruction mode:1T
* 作 者:	 XCY
* 修改日期: 2012年3月27日
*
*************************************************************************************/
#include <reg52.h>
#include <intrins.h>


typedef unsigned char 	BYTE;
typedef unsigned int 	WORD;


sfr AUXR = 0x8e;
sfr S2CON = 0x9a;
sfr S2BUF = 0x9b;
sfr BRT = 0x9c;
sfr IAP_DATA = 0XC2;
sfr IAP_ADDRH = 0XC3;
sfr IAP_ADDRL = 0XC4;
sfr IAP_CMD = 0XC5;
sfr IAP_TRIG = 0XC6;
sfr IAP_CONTR = 0XC7;


#define CMD_IDLE 	0
#define CMD_READ 	1
#define CMD_PROGRAM 2
#define CMD_ERASE 	3
#define BAUDBRT 0
#define TIMER1 1
#define S2RI 0X01
#define S2TI 0x02


//config
#define IAP_ADDRESS 0x0000
//const float code CRYSTAL = 18.432;
#define CRYSTAL	18.432
#define BAUDRATE_GENERATOR BAUDBRT
#define UART 2
#define ENABLE_IAP 0X82//sysclk<20m


void InitUART1(void);	//串口1初始化 使用定时器1作为波特率发生器
void InitUART1BRT(void);//串口1初始化 使用独立波特率发生器
void InitUART2(void);	//串口2初始化 必须使用独立波特率发生器
void Uart1Sendbyte(BYTE c);
void Uart2Sendbyte(BYTE c);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);


BYTE data global_c,global_d;
void delay10ms(void)   //误差 -0.054253472222us
{
    unsigned char a,b,c;
    for(c=4;c>0;c--)
        for(b=52;b>0;b--)
            for(a=220;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}
void main()
{
	WORD data i;
	BYTE data c;


#if UART == 1 && BAUDRATE_GENERATOR == TIMER1 	//串口1 定时器1
	InitUART1();
#elif UART == 1 && BAUDRATE_GENERATOR == BAUDBRT 	//串口1 独立波特率
	InitUART1BRT();
#elif UART == 2								 //串口2 只能使用独立波特率
	InitUART2();
#endif


	//IapEraseSector(IAP_ADDRESS);	  //erase


	//for(i = 0; i < 512; i++)  //check all byte is 0xff
		//if(IapReadByte(IAP_ADDRESS+i) != 0xff)
		//	goto Error;


//	for(i = 0; i < 512; i++)  //write
	//	IapProgramByte(IAP_ADDRESS+i,(BYTE)i);


	for(i = 0; i < 512; i++)  //read
	{
		c = IapReadByte(IAP_ADDRESS+i);
		Uart2Sendbyte(c);		  //send
		if(c != (BYTE)i)
			goto Error;
	}
	P2 = 0xfe;
	while(1);
Error:
	P1 = 0xdf;
	while(1);
	 
}
					 
void InitUART1(void)	//串口1初始化 使用定时器1作为波特率发生器
{
//9600bps timer mode:12T 8位数据
	PCON &= 0x7f;
    TMOD = TMOD & 0x0f;
	TMOD = TMOD | 0x20;
    SCON = 0x50;
 
#if CRYSTAL == 18.432
	TH1 = 0xFB;	
#elif CRYSTAL == 11.0592
    TH1 = 0xFD;
#endif
	TL1 = TH1;
	AUXR &= 0xbf;
	AUXR &= 0xfe;
	ET1 = 0;
	EA = 1;
    ES = 1;
    TR1 = 1;
}


void InitUART1BRT()		
{	
	//9600bps	timer mode:12T 8位数据
	PCON &= 0x7f;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
#if CRYSTAL == 18.432
	BRT = 0xFB;		//设定独立波特率发生器重装值
#elif CRYSTAL == 11.0592
	BRT = 0xFD;
#endif
	AUXR &= 0xfb;		//独立波特率发生器时钟为Fosc/12,即12T
	AUXR |= 0x01;		//串口1选择独立波特率发生器为波特率发生器
	AUXR |= 0x10;		//启动独立波特率发生器
	EA = 1;
    ES = 1;
}


void InitUART2()	//串口2初始化 必须使用独立波特率发生器  
{
	//9600bps	timer mode:12T	8位数据
	AUXR &= 0xf7;		//波特率不倍速
	S2CON = 0x50;		//8位数据,可变波特率
#if CRYSTAL == 18.432
	BRT = 0xfb;		   //设定独立波特率发生器重装值
#elif CRYSTAL == 11.0592
	BRT = 0Xfd;		   //设定独立波特率发生器重装值
#endif
	AUXR &= 0xfb;		//独立波特率发生器时钟为Fosc/12,即12T
	AUXR |= 0x10;		//启动独立波特率发生器
	EA = 1;
    ES = 1;
}


void Uart1Sendbyte(BYTE c)
{
	SBUF = c;
	while(!TI);
	TI = 0;
}


void Uart2Sendbyte(BYTE c)
{
	S2BUF = c;
	while(!(S2CON & S2TI));
	S2CON &= 0XFD;
}


void Uart1_Int() interrupt 4 using 1 //using 1:使用第一组寄存器
//(对于同级中断,用同样的寄存器组,因为不会中断嵌套,就不会出问题;
//对于不同级别的中断,一定不能使用同组寄存器,嵌套可能改变寄存器的值,引起错误)
{
	if(RI)	//串口每接收完1帧,硬件置1 RI,请求中断。
	{	 	//(其实就是请求把RI置0并且取走数据,不然还能干什么呢?
			//当然你可以加入自己想要的功能在里面)
		global_c = SBUF;
		SBUF = global_c;
		RI = 0;			
		
	}
	else TI = 0; 		
}


void Uart2_Int() interrupt 8 using 1
{
	if(S2CON&S2RI)
	{
		S2CON &= 0XFE;
		global_d = S2BUF;
		SBUF  = global_d; 
	}
	else S2CON &= 0XFD;
}


void IapIdle()
{
	IAP_CONTR &= 0X7F;  //DISABLE IAP FUNCTION
	IAP_CMD = 0;
	IAP_TRIG = 0;		//CLEAR TRIG REGESTER
	IAP_ADDRH = 0X2000;
	IAP_ADDRL = 0;
}


BYTE IapReadByte(WORD addr)
{
	BYTE dat;


	IAP_CONTR = ENABLE_IAP;	//使能IAP功能
	IAP_CMD = CMD_READ;		//说明是读还是写还是擦除
	IAP_ADDRL = addr;		//给定要操作的扇区地址
	IAP_ADDRH = addr>>8;
	IAP_TRIG = 0X5A;        //IAP触发开关 先送5A后送A5才能触发,IAP命令才能生效 每次读写都要重新送值
	IAP_TRIG = 0XA5;
	_nop_();				//延时,等待读取
	dat = IAP_DATA;			//将读取的数据赋值给dat
	IapIdle();				//将IAP功能设置成空闲


	return dat;
	
}


void IapProgramByte(WORD addr, BYTE dat)
{
	IAP_CONTR = ENABLE_IAP;
	IAP_CMD = CMD_PROGRAM;
	IAP_ADDRL = addr;
	IAP_ADDRH = addr>>8;
	IAP_DATA = dat;
	IAP_TRIG = 0X5A;
	IAP_TRIG = 0XA5;
	_nop_();
	IapIdle();
}


void IapEraseSector(WORD addr)
{
	IAP_CONTR = ENABLE_IAP;
	IAP_CMD = CMD_ERASE;
	IAP_ADDRL = addr;
	IAP_ADDRH = addr>>8;
	IAP_TRIG = 0X5A;
	IAP_TRIG = 0XA5;
	_nop_();
	IapIdle();
}

你可能感兴趣的:(51单片机EEPROM(E2PROM)测试程序,发送到串口 带独立波特率发生器测试)