ningling_21 发表于 2014-8-5 15:30
看看头文件中 寄存器定义对不对。。。
sfr IAP_DATA = 0xC2; //ISP/IAP Flash数据寄存器
#include<reg51.h>
#include<intrins.h>
#define SomeNop();{_nop_();_nop_();}
#define INC(x,y) if(++x>=y) x=0
sbit P0_4=P0^4;
typedef unsigned char BYTE;
typedef unsigned char WORD;
/*声明关联IAP的特殊功能寄存器*/
sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;
/*定义ISP/IAP/EEPROM命令*/
#define CMD_IDLE 0;
#define CMD_READ 1;
#define CMD_PROGRAM 2;
#define CMD_ERASE 3;
/*声明串口的特殊功能寄存器*/
sfr AUXR = 0x8E;
sfr AUXR1 = 0xA2;
sfr BRT = 0x9c;
#define ENABLE_IAP 0x83 //允许IAP,晶振11.0592M<12M,选择3
#define IAP_ADDRESS1 0x0000
#define IAP_ADDRESS2 0x0200
#define IAP_ADDRESS3 0x0400
sbit RE=P3^5;
unsigned int f68,faa;
unsigned char Time1;
unsigned char TempH1,TempL1;
unsigned char addrH1,addrL1;
unsigned char TxTime;
unsigned char TempH,TempL;
unsigned char addrH,addrL;
unsigned char MingLing[64]; //命令储存数组
unsigned char Pwrite=0; //命令数组计数
unsigned char Pread=0;
unsigned char HYMingLing[12]; //命令储存数组
unsigned int f10ms,fuart,u10ms ; //接收数据标志
//void IapEraseSector(WORD addr);
/************************************************************
延时函数
************************************************************/
/*函数功能:延时1ms*/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*函数功能:延时若干秒,入口参数:n*/
void delay (unsigned char n)
{
unsigned char i;
for (i=0;i<n;i++)
delay1ms();
}
/***********************************************************
EEPROM设置:把采集周期、温度门限、系列号写入
***********************************************************/
/*关闭IAP功能,使MCU进入安全模式*/
void IAP_Disable()
{
IAP_CONTR=0; //关闭IAP功能
IAP_CMD=0; //清命令寄存器,使寄存器无命令
IAP_TRIG=0; //清触发寄存器,使触发寄存器无触发
IAP_ADDRH=0x80; //数据指针指向non-EEPROM地方
IAP_ADDRL=0; //清IAP地址防止被误用
}
/*从EEPROM中读一个字节,入口参数:addr,出口参数:Flash data*/
BYTE IapReadByte(WORD addr)
{
BYTE dat;
IAP_CONTR=ENABLE_IAP; //打开IAP功能,设置flash操作等待时间
IAP_CMD=CMD_READ; //IAP/ISP/EEPROM字节读命令
IAP_ADDRH=addr; //设置目标单元位置的高8位地址
IAP_ADDRL=addr>>8; //设置目标单元位置的低8位地址
IAP_TRIG=0x5a; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此搜索
IAP_TRIG=0xa5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
dat=IAP_DATA;
IAP_Disable();
return dat;
}
/*写入字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据*/
void IapProgramByte(WORD addr,BYTE dat)
{
IAP_CONTR=ENABLE_IAP; //打开 IAP 功能, 设置Flash 操作等待时间
IAP_CMD=CMD_PROGRAM; //IAP/ISP/EEPROM 字节编程命令
IAP_ADDRL=addr; //设置目标单元地址的高8 位地址
IAP_ADDRH=addr>>8; //设置目标单元地址的低8 位地址
IAP_DATA=dat; //要编程的数据先送进IAP_DATA 寄存器
IAP_TRIG=0X5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG=0XA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*擦除扇区, 入口:DPTR = 扇区地址*/
void IapEraseSector(WORD addr)
{
IAP_CONTR=ENABLE_IAP; //打开 IAP 功能, 设置Flash 操作等待时间
IAP_CMD=CMD_ERASE; //IAP/ISP/EEPROM 扇区擦除命令
IAP_ADDRL=addr; //设置目标单元地址的高8 位地址
IAP_ADDRH=addr>>8; //设置目标单元地址的低8 位地址
IAP_TRIG=0X5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG=0XA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*把采集周期、温度门限、系列号写入1,2,3号扇区*/
void SheZhiCanShu()
{
IapEraseSector(IAP_ADDRESS1);
delay(10);
IapProgramByte(0x0000,0xAA);
_nop_();
IapProgramByte(0x0002,0x01);
_nop_();
IapProgramByte(0x0004,0x00);
_nop_();
IapProgramByte(0x0006,0x0A);
_nop_();
IapProgramByte(0x0008,0x00);
_nop_();
IapProgramByte(0x000A,0x01);
_nop_();
}
/*把采集周期、温度门限、系列号读出*/
void DuChuCanShu()
{
TxTime=IapReadByte(0x0002);
_nop_();
TempH=IapReadByte(0x0004);
_nop_();
TempL=IapReadByte(0x0006);
_nop_();
addrH=IapReadByte(0x0008);
_nop_();
addrL=IapReadByte(0x000A);
_nop_();
/* if(Data!=0xAA)
{
SheZhiCanShu();
}*/
}
/************************************************************
定时器T0,普通定时,做数据接收是否完成标志
************************************************************/
/*定时器中断*/
void T0_time(void) interrupt 1
{
TF0=0;
TR0=0; //关中断
--u10ms;
if(u10ms==0)
{
f10ms=1;
}
TH0=0xfe; //重新赋初值
TL0=0x0b;
TR0=1; //开中断
}
/*定时器初始化*/
void T0_init()
{
TMOD=0x01; //设置定时器0为工作方式1
TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
TL0=0x0b;
ET0=1; //允许定时中断
TR0=0; //启动定时中断
}
/************************************************************
485通信
************************************************************/
/*485串口初始化,独立波特率*/
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7f; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
BRT = 0xFD; //设定独立波特率发生器重装值
AUXR &= 0xfb; //独立波特率发生器时钟为Fosc/12,即12T
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10; //启动独立波特率发生器
AUXR1=0x80; //串口P1
ES=1;
// EA=1;
}
/*485串口中断程序*/
void USART_TI(void) interrupt 4
{
if(RI==1)
{
RI=0;
MingLing[Pwrite]=SBUF; //把命令保存在数组里
INC(Pwrite,64); //防止数组溢出
if(MingLing[0]==0x68)
{
f68=1;
}
else
{
Pwrite=0;
}
}
}
/*命令解析,并进行相对应的回应*/
void JieXiMingLing()
{
unsigned int i;
unsigned char CRC=0;
if(Pwrite>=6)
{
if(f68==1) //命令首字节为0x68,否则无效
{
if(MingLing[1]==0x77) //地址查询命令
{
if((MingLing[2]==0x00)&&(MingLing[3]==0x00)&&(MingLing[4]==0xdf)&&(MingLing[5]==0x0d))
{
HYMingLing[0]=0x77;
HYMingLing[1]=0x68;
HYMingLing[2]=addrH;
HYMingLing[3]=addrL;
HYMingLing[4]=0x0d;
RE=1;
for(i=0;i<5;i++)
{
SBUF=HYMingLing; //查询地址回应
while(!TI);
TI=0;
}
RE=0;
Pwrite=0;
Pread=0;
}
}
}
}
}
/***************************************************************
主函数
***************************************************************/
void main()
{
// unsigned int i;
unsigned char Data;
delay(50);
RE=0;
UartInit();
delay(10);
T0_init();
delay(10);
EA=1; //打开总中断
Data=IapReadByte(0x0000);
if(Data!=0xAA)
{
SheZhiCanShu();
}
while(1)
{
DuChuCanShu();
if(Pwrite!=Pread)
{
Pread=Pwrite;
TR0=1;
u10ms=2;
f10ms=0;
fuart=1;
}
if((f10ms==1)&&(fuart==1))
{
fuart=0;
TR0=0;
JieXiMingLing();
}
}
}
看看我完整的程序,应该回应我77 68 00 01 0D,现在回应总是77 68 FF FF 0D,感觉没有读出EEPROM中的数据。 |