- #include <reg51.h>
- #include <intrins.H>
- //#include <EEPROM.h>
- #define uchar unsigned char
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- /*Declare SFR associated with the IAP */
- sfr AUXR = 0x8E;
- sfr IAP_DATA = 0xE2; //Flash data register
- sfr IAP_ADDRH = 0xE3; //Flash address HIGH
- sfr IAP_ADDRL = 0xE4; //Flash address LOW
- sfr IAP_CMD = 0xE5; //Flash command register
- sfr IAP_TRIG = 0xE6; //Flash command trigger
- sfr IAP_CONTR = 0xE7; //Flash control register
- /*Define ISP/IAP/EEPROM command*/
- #define CMD_IDLE 0 //Stand-By
- #define CMD_READ 1 //Byte-Read
- #define CMD_PROGRAM 2 //Byte-Program
- #define CMD_ERASE 3 //Sector-Erase
- #define ENABLE_IAP 0x82 //if SYSCLK<20MHz
- #define IAP_ADDRESS 0x0000
- sbit K1=P1^0;
- sbit K2=P1^1;
- sbit K3=P1^2;
- sbit K4=P1^3;
- sbit K5=P1^4;
- sbit K6=P1^5;
- sbit K7=P1^6;
- sbit K8=P1^7;
- uchar dat;
- uchar t,r,ii;
- uchar add;//掉電保持485地址
- uchar j=0;
- bit flag_zx=0;
- uchar sendBuf[10];
- uchar receBuf[10];
- bit busy;
- bit bz1=0;
- bit bz2=0;
- bit bz3=0;
- bit bz4=0;
- bit bz5=0;
- bit bz6=0;
- bit bz7=0;
- bit bz8=0;
- void Delay(BYTE n);
- void IapIdle();
- BYTE IapReadByte(WORD addr);
- void IapProgramByte(WORD addr, BYTE dat);
- void IapEraseSector(WORD addr);
- /*********************************************
- 延時函數
- *********************************************/
- void delay(uchar t)
- {
- uchar i,j;
- for(i=0;i<t;i++)
- for(j=13;j>0;j--);
- }
- /*********************************************
- 串口初始化,波特率9600,方式1
- **********************************************/
- void Init_Com(void) //9600bps@11.0592MHz
- {
- PCON &= 0x7F; //波特率不倍速
- SCON = 0x50; //8位數據,可變波特率
- AUXR &= 0xBF; //定時器時鐘12T模式
- AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器
- TMOD &= 0x0F; //設置定時器模式
- TMOD |= 0x20; //設置定時器模式
- TL1 = 0xFD; //設置定時初始值
- TH1 = 0xFD; //設置定時重載值
- ET1 = 0; //禁止定時器%d中斷
- TR1 = 1; //定時器1開始計時
- // ES=1;//查詢方式不需開中斷
- // EA=1;
- }
- /***********發送函數***************************/
- void senduart2()
- {
- //RS485_DIR=1;
- SBUF=sendBuf[0];while(!TI);TI=0;
- SBUF=sendBuf[1];while(!TI);TI=0;
- SBUF=sendBuf[2];while(!TI);TI=0;
- SBUF=sendBuf[3];while(!TI);TI=0;
- SBUF=sendBuf[4];while(!TI);TI=0;
- }
- /******************清空發送緩沖區***************/
- void clear_receBuf()
- {
- uchar i;
- for(i=0;i<5;i++)
- {
- receBuf[i]=0;
- }
- }
- /************************************
- 主函數
- ************************************/
- void main()
- {
- delay(10);
- clear_receBuf();
- Init_Com();//串口初始化
- add=IapReadByte(0);//add=0x00;
- // P1=IapReadByte(0x00);
- while(1)
- {
- if(RI) //如果有接收
- {
- RI=0; //接收標志清零
- P1=SBUF; //獲取接收寄存器數據
- SBUF=P1; //數據返回上位機
- while(!TI); //等待發送完成
- TI=0; //發送標志位清0
- IapEraseSector(0x00); //擦除扇區
- IapProgramByte(0x00,P1);//寫入新數據*/
-
- /* if(RI)//如果有接收
- {
- RI=0;//接收標志清零
- receBuf[r]=SBUF;//把接收的數據存到BUT數組中*/
- if(receBuf[0]==0xaa)//驗證數據頭,否則下次接收覆蓋receBuf[0]
- {
- r++;
- if(r>=5)
- {
- r=0;
- flag_zx=1;
- }
- }
- }
- if(flag_zx==1)
- {
- flag_zx=0;
-
- // 0 1 2 3 4
- //起始位 地址位 功能位 數據位 結束位
- if((receBuf[0]==0xaa)&&(receBuf[4]==0xbb)&&(receBuf[1]==add))//如果開始位和結束位,還有地址都正確,進行下一步判斷
- {
- if(receBuf[2]==0x01) //修改板子地址
- {
- add=receBuf[3];
- IapEraseSector(0); //擦除扇區
- IapProgramByte(0,add);//寫入新的地址
- sendBuf[0]=0xaa;
- sendBuf[1]=add;
- sendBuf[2]=0x00;
- sendBuf[3]=add;
- sendBuf[4]=0xbb;
- senduart2();
- }
- else if(receBuf[2]==0x02) //打開單路繼電器
- {
- switch(receBuf[3])
- {
- case 0x01: K1=0; break;
- case 0x02: K2=0; break;
- case 0x03: K3=0; break;
- case 0x04: K4=0; break;
- case 0x05: K5=0; break;
- case 0x06: K6=0; break;
- case 0x07: K7=0; break;
- case 0x08: K8=0; break;
- }
- }
- else if(receBuf[2]==0x03) //關閉單路繼電器
- {
- switch(receBuf[3])
- {
- case 0x01: K1=1; break;
- case 0x02: K2=1; break;
- case 0x03: K3=1; break;
- case 0x04: K4=1; break;
- case 0x05: K5=1; break;
- case 0x06: K6=1; break;
- case 0x07: K7=1; break;
- case 0x08: K8=1; break;
- }
- }
- else if(receBuf[2]==0x04) //打開全部繼電器
- {
- if(receBuf[3]==0xff)
- {
- K1=0;
- K2=0;
- K3=0;
- K4=0;
- K5=0;
- K6=0;
- K7=0;
- K8=0;
- /*sendBuf[0]=0xaa;
- sendBuf[1]=add;
- sendBuf[2]=0xff;
- sendBuf[3]=0x00;
- sendBuf[4]=0xbb;
- senduart2();*/
- }
- }
- else if(receBuf[2]==0x05) //關閉全部繼電器
- {
- if(receBuf[3]==0x00)
- {
- K1=1;
- K2=1;
- K3=1;
- K4=1;
- K5=1;
- K6=1;
- K7=1;
- K8=1;
- /* sendBuf[0]=0xaa;
- sendBuf[1]=add;
- sendBuf[2]=0x07;
- sendBuf[3]=0x00;
- sendBuf[4]=0xbb;
- senduart2();*/
- }
- }
- else if(receBuf[2]==0x06) //查詢繼電器
- {
- sendBuf[0]=0xaa;
- sendBuf[1]=add;
- sendBuf[2]=0x07;
- sendBuf[3]=0xfe;
- sendBuf[4]=0xbb;
- switch(receBuf[3])
- {
- case 0x01: if(K1==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x02: if(K2==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x03: if(K3==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x04: if(K4==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x05: if(K5==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x06: if(K6==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x07: if(K7==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- case 0x08: if(K8==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
- default:break;
- }
- senduart2();
- }
- }
- if((receBuf[0]==0xaa)&&(receBuf[1]==0x00)&&(receBuf[2]==0x00)&&(receBuf[3]==0x00)&&(receBuf[4]==0xbb))
- {
- add=0x00;
- IapEraseSector(0); //擦除扇區
- IapProgramByte(0,0);//寫入新的地址
- sendBuf[0]=0xaa;
- sendBuf[1]=add;
- sendBuf[2]=0x07;
- sendBuf[3]=0x00;
- sendBuf[4]=0xbb;
- senduart2();
- }
- clear_receBuf();
- }
- }
- }
- /*----------------------------
- Disable ISP/IAP/EEPROM function
- Make MCU in a safe state
- ----------------------------*/
- void IapIdle()
- {
- IAP_CONTR = 0; //Close IAP function
- IAP_CMD = 0; //Clear command to standby
- IAP_TRIG = 0; //Clear trigger register
- IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area
- IAP_ADDRL = 0; //Clear IAP address to prevent misuse
- }
- /*----------------------------
- Read one byte from ISP/IAP/EEPROM area
- Input: addr (ISP/IAP/EEPROM address)
- Output:Flash data
- ----------------------------*/
- BYTE IapReadByte(WORD addr)
- {
- BYTE dat; //Data buffer
- IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
- IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command
- IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
- IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
- IAP_TRIG = 0x46; //Send trigger command1 (0x46)
- IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
- _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
- dat = IAP_DATA; //Read ISP/IAP/EEPROM data
- IapIdle(); //Close ISP/IAP/EEPROM function
- return dat; //Return Flash data
- }
- /*----------------------------
- Program one byte to ISP/IAP/EEPROM area
- Input: addr (ISP/IAP/EEPROM address)
- dat (ISP/IAP/EEPROM data)
- Output:-
- ----------------------------*/
- void IapProgramByte(WORD addr, BYTE dat)
- {
- IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
- IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command
- IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
- IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
- IAP_DATA = dat; //Write ISP/IAP/EEPROM data
- IAP_TRIG = 0x46; //Send trigger command1 (0x46)
- IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
- _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
- IapIdle();
- }
- /*----------------------------
- Erase one sector area
- Input: addr (ISP/IAP/EEPROM address)
- Output:-
- ----------------------------*/
- void IapEraseSector(WORD addr)
- {
- IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
- IAP_CMD = CMD_ERASE; //Set ISP/IAP/EEPROM ERASE command
- IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
- IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
- IAP_TRIG = 0x46; //Send trigger command1 (0x46)
- IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
- _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
- IapIdle();
- }
復制代碼
/****************適當的調整后,調試沒有報錯。 在Debug時,只在if(RI)和if(flag_zx==1)跳轉;此外用STC-IAP燒錄后出現控制紊亂,繼電器燈一會亮一會不亮;反復修改再燒錄,開發板閃一下后;STC-IAP顯示正在檢測單片機。。。再也連不上了*****/ |