/
** 文件名称: 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#include 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<20mvoid 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 定时器1InitUART1();#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); //sendif(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.432TH1 = 0xFB; #elif CRYSTAL == 11.0592TH1 = 0xFD;#endifTL1 = 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.432BRT = 0xFB; //设定独立波特率发生器重装值#elif CRYSTAL == 11.0592BRT = 0xFD;#endifAUXR &= 0xfb; //独立波特率发生器时钟为Fosc/12,即12TAUXR |= 0x01; //串口1挑选独立波特率发生器为波特率发生器AUXR |= 0x10; //发动独立波特率发生器EA = 1;ES = 1;}void InitUART2() //串口2初始化 有必要运用独立波特率发生器 {//9600bps timer mode:12T 8位数据AUXR &= 0xf7; //波特率不倍速S2CON = 0x50; //8位数据,可变波特率#if CRYSTAL == 18.432BRT = 0xfb; //设定独立波特率发生器重装值#elif CRYSTAL == 11.0592BRT = 0Xfd; //设定独立波特率发生器重装值#endifAUXR &= 0xfb; //独立波特率发生器时钟为Fosc/12,即12TAUXR |= 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 FUNCTIONIAP_CMD = 0;IAP_TRIG = 0; //CLEAR TRIG REGESTERIAP_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; //将读取的数据赋值给datIapIdle(); //将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();}