/** 文件名稱: eeprom.c * 摘 要: 對(duì)EEPROM某個(gè)扇區(qū)進(jìn)行讀、寫和擦除,并發(fā)送到串口UART=9600 8位數(shù)據(jù) CRYSTAL=18.432 TIMER_MODE=12T(EEPROM就是DATA FLASH,擦除只能按扇區(qū),讀寫可以按字節(jié),字節(jié)為0XFF時(shí)才可以寫)* 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初始化 使用定時(shí)器1作為波特率發(fā)生器void InitUART1BRT(void);//串口1初始化 使用獨(dú)立波特率發(fā)生器void InitUART2(void); //串口2初始化 必須使用獨(dú)立波特率發(fā)生器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 定時(shí)器1InitUART1();#elif UART == 1 && BAUDRATE_GENERATOR == BAUDBRT //串口1 獨(dú)立波特率InitUART1BRT();#elif UART == 2 //串口2 只能使用獨(dú)立波特率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初始化 使用定時(shí)器1作為波特率發(fā)生器{//9600bps timer mode:12T 8位數(shù)據(jù)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位數(shù)據(jù)PCON &= 0x7f; //波特率不倍速SCON = 0x50; //8位數(shù)據(jù),可變波特率#if CRYSTAL == 18.432BRT = 0xFB; //設(shè)定獨(dú)立波特率發(fā)生器重裝值#elif CRYSTAL == 11.0592BRT = 0xFD;#endifAUXR &= 0xfb; //獨(dú)立波特率發(fā)生器時(shí)鐘為Fosc/12,即12TAUXR |= 0x01; //串口1選擇獨(dú)立波特率發(fā)生器為波特率發(fā)生器AUXR |= 0x10; //啟動(dòng)獨(dú)立波特率發(fā)生器EA = 1;ES = 1;}void InitUART2() //串口2初始化 必須使用獨(dú)立波特率發(fā)生器 {//9600bps timer mode:12T 8位數(shù)據(jù)AUXR &= 0xf7; //波特率不倍速S2CON = 0x50; //8位數(shù)據(jù),可變波特率#if CRYSTAL == 18.432BRT = 0xfb; //設(shè)定獨(dú)立波特率發(fā)生器重裝值#elif CRYSTAL == 11.0592BRT = 0Xfd; //設(shè)定獨(dú)立波特率發(fā)生器重裝值#endifAUXR &= 0xfb; //獨(dú)立波特率發(fā)生器時(shí)鐘為Fosc/12,即12TAUXR |= 0x10; //啟動(dòng)獨(dú)立波特率發(fā)生器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:使用第一組寄存器//(對(duì)于同級(jí)中斷,用同樣的寄存器組,因?yàn)椴粫?huì)中斷嵌套,就不會(huì)出問題;//對(duì)于不同級(jí)別的中斷,一定不能使用同組寄存器,嵌套可能改變寄存器的值,引起錯(cuò)誤){if(RI) //串口每接收完1幀,硬件置1 RI,請(qǐng)求中斷。{ //(其實(shí)就是請(qǐng)求把RI置0并且取走數(shù)據(jù),不然還能干什么呢?//當(dāng)然你可以加入自己想要的功能在里面)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; //給定要操作的扇區(qū)地址IAP_ADDRH = addr>>8;IAP_TRIG = 0X5A; //IAP觸發(fā)開關(guān) 先送5A后送A5才能觸發(fā),IAP命令才能生效 每次讀寫都要重新送值IAP_TRIG = 0XA5;_nop_(); //延時(shí),等待讀取dat = IAP_DATA; //將讀取的數(shù)據(jù)賦值給datIapIdle(); //將IAP功能設(shè)置成空閑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();}
評(píng)論