craaazyfor 发表于 2013-11-15 11:10 
初步看没问题,都是按IAP来的,至于应用,你可以那样去验证
#include"reg51.h"
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
/*Declare SFR associated with the ISP */
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 0x00 //Stand-By
#define CMD_READ 0x00 //unsigned char-Read
#define CMD_PROGRAM 0x02 //unsigned char-Program
#define CMD_ERASE 0x03 //Sector-Erase
/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81 //if SYSCLK<24MHz
//#define ENABLE_IAP 0x82 //if SYSCLK<200MHz
#define ENABLE_IAP 0x83 //if SYSCLK<12MHz
//#define ENABLE_IAP 0x80 //if SYSCLK<6MHz
#define IAP_ADDRESS 0x0000
/**AD特殊寄存器***/
sfr ADC_DATA =0xc6;
sfr ADC_LOW2 =0xbe;
sfr ADC_CONTR =0xc5;
sfr P1M0 =0x91;
sfr P1M1 =0x92;
/***按键定义*****/
sbit KEY_P3_4 =P3^4; //左边拨动开关(拨向左:P3^4==0,表示需要标定电压;否则不需要标定)
sbit KEY_P0_0 =P0^0; //右边红色按钮(按下时:P0^0==0,表示开始标定电压;否则不标定)
sbit led=P1^1;
void ISP_IAP_Disable();
/***程序用到的定义****/
uint i,j,AD_finished=0,pj=0;mj=0,x=1,su[1],y;
uchar num,result,di,flag;
/**********延时函数*****************/
void delayms(uint xms)
{
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
/*********串口/定时器初始化***************/
void init()
{
TMOD=0x21;//设定T1定时器工作方式2 0010 0001
TH1=0xfd;//T1定时器高8位赋值
TL1=0xfd;//T1定时器低8位赋值
TH0=0x4c;//T0定时器高8位赋值
TL0=0x00;//T0定时器低8位赋值
SCON=0x40;//设定串口工作方式1
EA=1;//开中断
TR0=1;//开启定时器T0
TR1=1;//开启定时器T1
ET0=1;//开定时器0中断
ES=1;//允许串口中断
REN=1;//允许串口接收
}
void fas(uint a)//1.32===int 1.0//==132
{
ES=0;
SBUF=a;//接收数据
while(!TI);
TI=0;
ES=1;
}
/*********AD函数**************/
void AD_init()
{
P1M0=0x80;P1M1=0x00;
ADC_DATA=0;
ADC_CONTR=0xe0;//1110 0000开启启动电源和选择转换速度
delayms(60);
}
/*****AD转换函数*********/
uint getAD()
{
uchar AD_finished=0;
ADC_CONTR|=0x07; //1110 0000 | 1111 1111 或上AD口的值
ADC_CONTR|=0x08;//0000 1000启动AD电源
while(AD_finished==0)//等待A/D转换结束
(AD_finished=(ADC_CONTR&0x10));//0000 1000 & 0001 0000 =0000 0000查询ADC_FLAG位是否置1
ADC_CONTR=0Xf7;//1111 0111//关闭启动位
return ADC_DATA; //值返回给高8位
}
/*********定时中断***********/
void T0_time() interrupt 1
{
TH0=0x4c;
TL0=0x00;
num++;
if(num>=20)
{
num=0;
pj=1;
}
}
/****关闭ISP,IAP功能*******/
void ISP_IAP_Disable()
{
IAP_CONTR=0x00;//Close IAP function关闭控制寄存器
IAP_CMD =0x00;//clear command to standby清除命令备用
IAP_TRIG =0x00;//Clear trigger register
IAP_ADDRH=0x80;//Data ptr point to non-EEPROM area
IAP_ADDRL=0x00;//Clear IAP address to prevent misuse
}
/**向EEPROM16位地址读出8位数据**/
unsigned char IapReadINT8U(unsigned int addr)
{
unsigned char dat;
IAP_CONTR=ENABLE_IAP; // 打开IAP功能,设置Flash操作等待时间
IAP_CMD =CMD_READ; // 对用户的应用程序Flash区及数据Flash区字节读
IAP_ADDRH=addr>>8; //设置目标单元地址的高8位地址
IAP_ADDRL=addr; //设置目标单元地址的低8位地址
IAP_TRIG =0x46; //触发ISP_IAP命令字节1(0x46)
IAP_TRIG =0xb9; //触发ISP_IAP命令字节2(0xb9)
_nop_(); //延时一个机器周期
dat=IAP_DATA; //读出数据准备
ISP_IAP_Disable(); //关闭IAP,ISP功能
return dat; //返回给函数
}
/**向EEPROM16位地址写入8位数据**/
void IapProgramINT8U(unsigned int addr,unsigned char dat)
{
IAP_CONTR=ENABLE_IAP;//Open IAP function,and set wait time 打开IAP功能,设置Flash操作等待时间
IAP_CMD=CMD_PROGRAM;//对用户的应用程序Flash区及数据Flash区编程
IAP_ADDRH=addr>>8;//设置目标单元地址的高8位地址
IAP_ADDRL=addr;//设置目标单元地址的低8位地址
IAP_DATA=dat; //写入数据准备
IAP_TRIG=0x46;//Send trigger command1 (0x46)
IAP_TRIG=0xb9;//Send trigger command1 (0xb9)
_nop_(); //延时一个机器周期
ISP_IAP_Disable(); //关闭IAP,ISP功能
}
/**扇区擦除**/
void IapEraseSector(unsigned int addr)
{
IAP_CONTR = ENABLE_IAP;//打开IAP功能,设置Flash操作等待时间
IAP_CMD = CMD_ERASE;//对用户的应用程序Flash区及数据Flash区擦出
IAP_ADDRH=addr>>8;//设置目标单元地址的高8位地址
IAP_ADDRL=addr;//设置目标单元地址的低8位地址
IAP_TRIG=0x46;//Send trigger command1 (0x46)
IAP_TRIG=0xb9;//Send trigger command1 (0xb9)
_nop_();
ISP_IAP_Disable();
}
/*****定时1s去采集AD信号**********/
void AD_cj()
{
if(pj>=1)
{
pj=0;
mj++;
}
if(mj>=x)
{
mj=0;
fas(su[0]);
}
}
/****存电压值*********/
void dy()
{
if(KEY_P0_0==0)
{
delayms(20);
if(KEY_P0_0==0)
{
AD_init();
IapEraseSector(IAP_ADDRESS);//擦出扇区
IapProgramINT8U(IAP_ADDRESS,getAD());//从0x0000地址写入AD采样值
su[0]=IapReadINT8U(0x0000);//读出E2PROM中值赋给su【0】
//su[0]=getAD();
fas(su[0]);
while(!KEY_P0_0);
while(1);
}
}
}
/**主函数***/
void main()
{
init();
while(1)
{
//void IapProgramINT8U(unsigned int addr,unsigned char dat);
if(!KEY_P3_4)
{
dy();led=0; }
else
AD_cj();led=1;
}
}
我采用stc12c5608AD的单片机,在调试功能时我在按下 KEY_P0_0 时怎么串口没有发出AD采用值,
|