- 打卡等级:初来乍到
- 打卡总天数:2
- 最近打卡:2024-02-01 16:06:56
注册会员
- 积分
- 69
|
最近测试的STC32G12K128-USB在线升级这个没问题了,按照例程配置ISP程序128K全部为EEPROM。
但是在用户程序里有用到36字节EEPROM。现在把36字节地址设置eeprom为0x01FA00 但是读出的全是0XFF。
是不是eeprom地址有偏移?请大佬帮忙分析一下。
#define T1MS (65536 - FOSC/1000)
#define DFU_TAG 0x12abcd34 //DFU强制执行标志
#define IAP_BASE 0XFF0000 //基地址
#define EEPROM_ADDR 0x01FA00 //读写的EEPROM地址
long xdata DfuFlag _at_ 0x1ffc; //DFU标志, 定义在xdata的最后4字节
u8 const default_config[36] ={0X43,0X4C,0X41,0X56,0X48,0X50,0X20,0X01,0X10,0X0E,0X0E,0X3C,0X3C,
0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X32,0X2E,0X30,0X2E,0X30,0X00,0X00};
u8 RAM_CONFIG[36]; //保存写入读出的eeprom数据
char cnt8;
int cnt300;
int cnt500;
int cnt1000;
void sys_init()
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
TMOD = 0x00;
T0x12 = 1;
TL0 = T1MS;
TH0 = T1MS >> 8;
TR0 = 1;
ET0 = 1;
DfuFlag = 0; //上电正常执行用户AP,时需要将DFU标志清零
}
void tm0_isr() interrupt 1 //1mS中断
{
if (cnt1000++ >= 1000) //1秒进入一次
{
cnt1000 = 0;
P21 = ~P21;
}
if(P32 == 0)
{
if(cnt8++ >= 127)
{
EUSB = 0; //失能USB中断
USBCON = 0x08; //失能usb功能与时钟;DP/DM使能下拉电阻
DfuFlag = DFU_TAG; //当需要执行用户ISP代码时,将强制执行标志赋值到DFU标志变量中
IAP_CONTR = 0x60; //软复位从ISP区执行
}
}else{
cnt8=0; //清除计数器
}
if (DeviceState == DEVSTATE_CONFIGURED) //如果USB配置没有完成,就直接退出
USB_polling();
}
void main()
{
sys_init();
uart_init();
EEPROM_read_n(EEPROM_ADDR, RAM_CONFIG,36); //读出配置
if((RAM_CONFIG[0] ==0XFF) || (RAM_CONFIG[0]==0))
{
do{
EEPROM_SectorErase(EEPROM_ADDR);
EEPROM_write_n(EEPROM_ADDR, default_config,36);
EEPROM_read_n(EEPROM_ADDR, RAM_CONFIG,36); //读出配置
}while((RAM_CONFIG[0] ==0XFF)||(RAM_CONFIG[0]==0));
}
usb_init();
EA = 1;//全局中断使能
while (1){}
}
///////////////////本程序是STC32G系列的内置EEPROM读写程序。/////////////////////////////////////////
#include "eeprom.h"
#define IAP_STANDBY() IAP_CMD = 0 //IAP空闲命令(禁止)
#define IAP_READ() IAP_CMD = 1 //IAP读出命令
#define IAP_WRITE() IAP_CMD = 2 //IAP写入命令
#define IAP_ERASE() IAP_CMD = 3 //IAP擦除命令
#define IAP_ENABLE() IAP_CONTR = IAP_EN; IAP_TPS = FOSC / 1000000
#define IAP_DISABLE() IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRE = 0xff; IAP_ADDRH = 0xff; IAP_ADDRL = 0xff
#define IAP_EN (1<<7)//使能eeprom操作
#define IAP_SWBS (1<<6)
#define IAP_SWRST (1<<5)
#define IAP_CMD_FAIL (1<<4)//EEPROM操作状态位
//========================================================================
// 函数: void ISP_Disable(void)
// 描述: 禁止访问ISP/IAP.
// 版本: V1.0, 2012-10-22
//========================================================================
void DisableEEPROM(void) //禁止访问EEPROM
{
IAP_CONTR = 0; //禁止ISP/IAP操作
IAP_CMD = 0; //去除ISP/IAP命令
IAP_TRIG = 0; //防止ISP/IAP命令误触发
IAP_ADDRE = 0xff; //将地址设置到非 IAP 区域
IAP_ADDRH = 0xff; //清0地址高字节
IAP_ADDRL = 0xff; //清0地址低字节,指向非EEPROM区,防止误操作
}
//========================================================================
// 函数: void EEPROM_Trig(void)
// 描述: 触发EEPROM操作.
// 版本: V1.0, 2014-6-30
//========================================================================
void EEPROM_Trig(void)
{
F0 = EA; //保存全局中断
EA = 0; //禁止中断, 避免触发命令无效
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5; //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
//送完A5H后,IAP命令立即被触发启动
//CPU等待IAP完成后,才会继续执行程序。
_nop_(); //由于STC32G是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
_nop_();
_nop_();
_nop_();
EA = F0; //恢复全局中断
}
//========================================================================
// 函数: void EEPROM_SectorErase(u32 EE_address)
// 描述: 擦除一个扇区.
// 参数: EE_address: 要擦除的EEPROM的扇区中的一个字节地址.
// 版本: V1.0, 2014-6-30
//========================================================================
void EEPROM_SectorErase(u32 EE_address)
{
IAP_ENABLE(); //宏调用, 设置等待时间,允许IAP操作,送一次就够
IAP_ERASE(); //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
//只有扇区擦除,没有字节擦除,512字节/扇区。
//扇区中任意一个字节地址都是扇区地址。
IAP_ADDRE = (u8)(EE_address >> 16); //送扇区地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = (u8)(EE_address >> 8); //送扇区地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (u8)EE_address; //送扇区地址低字节(地址需要改变时才需重新送地址)
EEPROM_Trig(); //触发EEPROM操作
DisableEEPROM(); //禁止EEPROM操作
}
//========================================================================
// 函数: void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u8 lenth)
// 描述: 读N个字节函数.
// 参数: EE_address: 要读出的EEPROM的首地址.
// DataAddress: 要读出数据的指针.
// length: 要读出的长度
// 返回: 0: 写入正确. 1: 写入长度为0错误. 2: 写入数据错误.
// 版本: V1.0, 2014-6-30
//========================================================================
void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u8 length)
{
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
IAP_READ(); //送字节读命令,命令不需改变时,不需重新送命令
do
{
IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = (u8)(EE_address >> 8); //送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (u8)EE_address; //送地址低字节(地址需要改变时才需重新送地址)
EEPROM_Trig(); //触发EEPROM操作
*DataAddress = IAP_DATA; //读出的数据送往
EE_address++;
DataAddress++;
}while(--length);
DisableEEPROM();
}
void IAPRead(u32 EE_address, u8 *DataAddress,u8 length)
{
u32 EEaddress;
do
{
EEaddress=(EE_address&0X1FFFF)/IAP_BASE;
*DataAddress =*(u8 far*)EEaddress;
EE_address++;
DataAddress++;
}while(--length);
}
//========================================================================
// 函数: u8 EEPROM_write_n(u32 EE_address,u8 *DataAddress,u8 length)
// 描述: 写N个字节函数.
// 参数: EE_address: 要写入的EEPROM的首地址.
// DataAddress: 要写入数据的指针.
// length: 要写入的长度
// 返回: 0: 写入正确. 1: 写入长度为0错误. 2: 写入数据错误.
// 版本: V1.0, 2014-6-30
//========================================================================
u8 EEPROM_write_n(u32 EE_address,u8 *DataAddress,u8 length)
{
u8 i;
u16 j;
u8 *p;
if(length == 0) return 1; //长度为0错误
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
i = length;
j = EE_address;
p = DataAddress;
IAP_WRITE(); //宏调用, 送字节写命令
do
{
IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = (u8)(EE_address >> 8); //送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (u8)EE_address; //送地址低字节(地址需要改变时才需重新送地址)
IAP_DATA = *DataAddress; //送数据到IAP_DATA,只有数据改变时才需重新送
EEPROM_Trig(); //触发EEPROM操作
EE_address++; //下一个地址
DataAddress++; //下一个数据
}while(--length); //直到结束
EE_address = j;
length = i;
DataAddress = p;
i = 0;
IAP_READ(); //读N个字节并比较
do
{
IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = (u8)(EE_address >> 8); //送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (u8)EE_address; //送地址低字节(地址需要改变时才需重新送地址)
EEPROM_Trig(); //触发EEPROM操作
if(*DataAddress != IAP_DATA) //读出的数据与源数据比较
{
i = 2;
break;
}
EE_address++;
DataAddress++;
}while(--length);
DisableEEPROM();
return i;
}
|
-
-
|