AI8H2K12U EEPROM 程序
#include <absacc.h>#define IAP_TPS_ 24 //等待参数
#define IAP_OFFSET 0x2E00 //EEPROM地址
void Iap_Idle(void)
{
IAP_CONTR&=~IAPEN;
IAP_CMD=IAP_IDL;
IAP_TRIG=0x00;
IAP_ADDRH=0x80;
IAP_ADDRL=0x00;
}
unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
{
return *(CBYTE+IAP_OFFSET+sector*0x0200+addr);
}
//unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
//{
// unsigned char dat;
// unsigned int add;
// add=sector*0x0200+addr;
// IAP_CONTR|=IAPEN;
// IAP_TPS=IAP_TPS_;
// IAP_CMD=IAP_READ;
// IAP_ADDRL=add;
// IAP_ADDRH=add>>8;
// IAP_TRIG=0x5A;
// IAP_TRIG=0xA5;
// _nop_();
// dat=IAP_DATA;
// Iap_Idle();
// return dat;
//}
void Iap_Program_Byte(unsigned char sector,unsigned int addr,unsigned char dat)
{
unsigned int add;
add=sector*0x0200+addr;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_WRITE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_DATA=dat;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
void Iap_Erase_Sector(unsigned char sector)
{
unsigned int add;
add=sector*0x0200;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_ERASE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
烧录时要选择 EEPROM 的大小
其实之前有想过直接使用MOVC的方式读取EEPROM的数据,但是目前来看,这种方式不具有普适性。因为EEPROM的大小是可以设置的,而且好像手册中页没有说明可以通过什么寄存器读取这个设置的EEPROM大小或者关于EEPROM的起始位置之类的(如果存在的,记得回来踢我一脚)。。如果调试人员对EEPROM的配置修改了,和程序里面的宏定义不匹配极可能会导致程序出现问题,增加调试成本。。
最后就还是选择了IAP的方式读取EEPROM数据,这样把无论设置EEPROM的大小是多少,只要是够用,就都能正确读取{:wunai:} 请教下,AI8H2K12U的EEPROM地址0x0000和其它地址是否有区别,目前发现0x0000程序中无法正常写入读取,换成其它地址就一切正常,在主程序开始前做写入和读取操作测试又正常{:4_167:}
#include <AI8H.H>
#include "Delay.h"
#include "STC8H_PWM.h"
#include "INT0and1.h"
#include "STC8_EEPROM.h"
#define PWM6_E0x0001//PWM6档位的EEPROM存储地址(0x0000无法使用原因不明)
u8 Key1; //档位变量
u8 PWM6_MOD; //PWM6初始占空比
bit PWM6_KG = 0; //PWM6开关状态
bit PWM6_UP = 0; //PWM6更新标识位
bit EEPROM_UP = 0;//EEPROM更新标识位
void main()
{
INT0and1_Init(); //外部中断初始化,一定要加在main主程序前
STC8H_PWM_Init(); //初始化硬件PWM
P3M0 &= ~0x0c; P3M1 &= ~0x0c; //P32/33设为准双向口
// IapEraseSector(IAP_ADDRESS1); //擦除第1扇区(写入地址所在扇区)
// IapProgramByte(0x0000,5); //在地址0x00F1写入Key1的值
// switch(IapReadByte(0x0000)) //读取EEPROM数据
switch(IapReadByte(PWM6_E)) //读取EEPROM数据
{
case 2:Key1 = 2;PWM6_MOD = 40;break;
case 3:Key1 = 3;PWM6_MOD = 50;break;
case 4:Key1 = 4;PWM6_MOD = 60;break;
case 5:Key1 = 5;PWM6_MOD = 70;break;
case 6:Key1 = 6;PWM6_MOD = 80;break;
case 7:Key1 = 7;PWM6_MOD = 90;break;
case 8:Key1 = 8;PWM6_MOD = 100;break;
default:Key1 = 1;PWM6_MOD = 30;break;
}
while (1)
{
if(PWM6_UP)
{
PWM6_UP = 0;//清除更新标识位
if(PWM6_KG)//判断开关状态
{
PWM_Set(6,PWM6_MOD);
}else
{
PWM_Set(6,0);
}
}
if(EEPROM_UP)
{
EEPROM_UP = 0; //清除更新标识位
IapEraseSector(IAP_ADDRESS1); //擦除第1扇区(写入地址所在扇区)
IapProgramByte(PWM6_E,Key1); //在地址0x00F1写入Key1的值
}
}
}
void INT_0(void) interrupt 0 //外部中断P32接口
{
Delay(50);//延时消抖
if(P32 == 0)
{
while(P32==0); //松手检测
PWM6_KG = ~PWM6_KG; //翻转开关状态
PWM6_UP = 1; //开启PWM6更新
}
}
void INT_1(void) interrupt 2 //外部中断P33接口
{
Delay(50);//延时消抖
if(P33==0)
{
while(P33 == 0);//松手检测
Key1++;
EEPROM_UP = 1;//开启EEPROM更新
switch(Key1)//判断档位
{
case 2:PWM6_MOD = 40;break;
case 3:PWM6_MOD = 50;break;
case 4:PWM6_MOD = 60;break;
case 5:PWM6_MOD = 70;break;
case 6:PWM6_MOD = 80;break;
case 7:PWM6_MOD = 90;break;
case 8:PWM6_MOD = 100;break;
default:Key1 = 1;PWM6_MOD = 30;break;
}
if(PWM6_KG) //如果PWM6开启,则开启PWM6更新
{
PWM6_UP = 1;
}
}
}
页:
[1]